Reputation: 161
I was wondering how the following code evaluates to 3.
(define (foo y) ((lambda (x) y) ((lambda (y)(* y y)) y)))
(foo 3)
I have been looking at it for a while and cannot seem to understand why the evaluation does not result in 9. Could someone provide a detailed step by step instruction on how this evaluates to 3?
Upvotes: 0
Views: 87
Reputation: 71070
With let
re-writing,
(define (foo y) ((lambda (x) y) ((lambda (y)(* y y)) y)))
(foo 3)
=
(let ([y 3]) ; by application
((lambda (x) y) ((lambda (y)(* y y)) y)))
=
(let ([y 3])
(let ([x ((lambda (y)(* y y)) y)]) ; by application
y ))
=
(let ([y 3])
(let ([x ((lambda (z)(* z z)) y)]) ; by alpha-renaming
y ))
=
(let ([y 3])
(let ([x (let ([z y]) ; by application
(* z z))])
y ))
=
(let ([y 3])
(let ([x (* y y)]) ; by let-elimination
y ))
=
(let ([y 3])
(let ([x 9]) ; by expression evaluation
y ))
=
(let ([y 3])
y ) ; by let-elimination
=
3 ; by let-elimination
As you can see, the nested (lambda (y)(* y y))
is situated in a nested scope, not affecting the y
which is finally returned, but only x
, which value, 9, is evaluated and then discarded.
Upvotes: 1
Reputation: 235984
Let's start by indenting the code in a way that it's easier to understand:
(define (foo y)
((lambda (x) y)
((lambda (y) (* y y))
y)))
Now let's evaluate it, from the inside-out:
(define (foo y)
((lambda (x) y)
((lambda (y) (* y y))
3))) ; pass the parameter
(define (foo y)
((lambda (x) y)
(* 3 3))) ; evaluate innermost lambda
(define (foo y)
((lambda (x) y) 9)) ; pass the result of evaluation
Aha! that's where we get the 3
. Even though we're passing a 9
as parameter (bound to x
), we're simply returning the value of the outermost y
parameter, which was 3
all along:
=> 3
Upvotes: 3