MastRofDsastR
MastRofDsastR

Reputation: 161

Explanation of evaluation for this Scheme procedure using lambdas

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

Answers (2)

Will Ness
Will Ness

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

Óscar López
Óscar López

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

Related Questions