ENV1:[a:x b:y ...].
ENVi.Parent = ENVj
f1: ParentEnv: ENVi
Param: x, y
Body: (* x y)
(define a 1)
(define b 2)
(define (h x) (+ x 100))
(define (targil f)
(define (g x) (lambda (x) (f (* x a))))
(let ((f h) (a 3))
(g b)))
ENV1: [a:1 b:2 h:f1 targil:f2]
f1: ParentEnv: ENV1
Param: x
Body: (+ x 100)
f2: ParentEnv: ENV1
Param: f
Body: (begin (define (g x) (lambda (x) (f (* x a))))
(let ((f h) (a 3))
(g b)))
EVAL (targil (lambda (x) (* x 2))) in ENV1
The first parameter (lambda (x) (* x 2)) is evaluated in ENV1. The result is:
f3: ParentEnv: ENV1
Param: x
Body: (* x 2)
FOR EACH PARAMETER ADD AN ENTRY IN THE NEW ENVIRONMENT:
ENV2: [f: f3]
THIS IS THE CRITICAL POINT Always use the ParentEnv of the function being evaluated (targil).
ENV2.parent = ENV1.
ENV2: [f:f3 g:f4]
f4: ParentEnv: ENV2
Param: x
Body: (lambda (x) (f (* x a)))
ENV3: [f:h a:3] ENV3.Parent = ENV2
ENV4: [x: 2]
ENV4.Parent = ENV2 [NOT ENV3!!!!!!!!!!!!!!]
f5: ParentEnv: ENV4
Param: x
Body: (f (* x a))
Eval ((targil (lambda (x) (* 2 x))) 5) in ENV1.
The function evaluates to f5 and the parameter to 5.
ENV5: [x: 5]
ENV5.Parent = ENV4 [NOT ENV1!!!!!!!!!!!!!!]
ENV5:[x:5]-->ENV4:[x:2]-->ENV2:[f:f3 g:f4]-->ENV1:[a:1 b:2 h:f1 targil:f2] x = 5 (defined in ENV5) a = 1 (defined in ENV1) f = f3 (defined in ENV2)We now need to evaluate: (f3 5). The same procedure is repeated:
ENV6: [x: 5]
ENV6.Parent = ENV1