1 / 68

PS4 Programming: Lambda Evaluation and Environment Binding

Learn how to evaluate lambda expressions in environments, bind variables in let and let* statements, and evaluate side-effecting data structures in PS4 programming.

vanalstyne
Download Presentation

PS4 Programming: Lambda Evaluation and Environment Binding

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. PS4 #6: if you got points off because you didn’t do an intersect with accessible and the start states, submit a re-grade. Today: let, let*, letrec in the env. model side-effecting lists (set-car!, set-cdr!) Tomorrow: more on side-effecting data structures (e.g., chains)

  2. To evaluate a lambda in environment E, build a closure. • To evaluate a (non-special form) combination: (f a1 ... an) in E: • evaluate f in E and get a closure c • evaluate each argument ai in E to get a value vi • apply the closure c to the values v1 ... vn • To apply a closure c to values v1 ... vn: • build a new frame, binding closure formal parameters to • actual parameters v1 ... vn • link the frame into the environment of the closure to yield a • new environment • evaluate the body of the closure in the new environment

  3. To evaluate: (let ((x1 e1) (x2 e2) ... (xn en)) e) in environment E: 1. evaluate e1, e2, ..., en in environment E producing values v1,v2,...,vn. 2. build a new frame that binds x1 to v1, x2 to v2, ..., xn to vn. 3. link the new frame into E to yield a new environment. 4. evaluate the body of the let, e, in the new environment.

  4. (let ((x 1) (y 2)) (* x y)) *: {mult} 1. evaluate 1 and 2 in the current env.

  5. (let ((x 1) (y 2)) (* x y)) *: {mult} x: 1 y: 2 2. build new frame with bindings 3. link it in to the env.

  6. (let ((x 1) (y 2)) (* x y)) *: {mult} x: 1 y: 2 4. evaluate body of let in new env.

  7. (let ((x 3) (y (* x x))) (* x y)) *: {mult} 1. evaluate 1 in environment to get 1...

  8. (let ((x 3) (y (* x x))) (* x y)) *: {mult} ...but evaluating (* x x) fails! (no binding for x in the environment!)

  9. Alternative: (let ((x1 e1) (x2 e2) ... (xn en)) e) in environment E, evaluate: ((lambda (x1 x2 ... xn) e) e1 e2 ... en)

  10. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult}

  11. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult}

  12. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult} args: (x y) body: (* x y) env :

  13. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult} args: (x y) body: (* x y) env : Now apply the closure to 1 and 2...

  14. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult} args: (x y) body: (* x y) env : x: 1 y: 2 ...and we get 2.

  15. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult} args: (x y) body: (* x y) env : x: 1 y: 2 afterwards, we continue evaluating in the top-level environment...

  16. (let ((x 1) (y 2)) => ((lambda (x y) (* x y)) 1 2) (* x y)) *: {mult} args: (x y) body: (* x y) env : x: 1 y: 2 and the intermediate closure and frame are garbage collected

  17. To evaluate: (let* ((x1 e1) (x2 e2) ... (xn en)) e) in environment E: 1. evaluate e1 in E to v1 2. add a new frame mapping x1 to v1, yielding E2 3. evaluate e2 in E2 to v2 4. add a new frame mapping x2 to v2, yielding E3 ... 2n-1. evaluate en in En to vn 2n. add a new frame mapping xn to vn, yielding E’ 2n+1. evaluate the body e in E’

  18. (let* ((x 3) (y (* x x))) (* x y)) *: {mult}

  19. (let* ((x 3) (y (* x x))) (* x y)) *: {mult} x:3

  20. (let* ((x 3) (y (* x x))) (* x y)) *: {mult} x:3 The (* x x) yields 9...

  21. (let* ((x 3) (y (* x x))) (* x y)) *: {mult} x:3 y:9

  22. (let* ((x 3) (y (* x x))) (* x y)) *: {mult} x:3 y:9 The (* x y) yields 3*9 = 27

  23. Alternative: (let* ((x1 e1) (x2 e2) ... (xn en)) e) in environment E, evaluate: (let ((x1 e1)) (((...(lambda (x1) (let ((x2 e2)) ((lambda (x2) ... => ... (let ((xn en)) ((lambda (xn) e)...)) e))) e1) e2) ... en)

  24. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x) ((lambda (y) (* x y)) (* x x))) 3) *: {mult}

  25. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x) ((lambda (y) (* x y)) (* x x))) 3) args: x body: env: *: {mult}

  26. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x) ((lambda (y) (* x y)) (* x x))) 3) args: x body: env: *: {mult} x:3

  27. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x) ((lambda (y) (* x y)) (* x x))) 3) args: x body: env: *: {mult} x:3

  28. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x)((lambda (y) (* x y)) (* x x))) 3) *: {mult} x:3

  29. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x)((lambda (y) (* x y)) (* x x))) 3) *: {mult} x:3 args: y body: (* x y) env:

  30. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x)((lambda (y) (* x y)) (* x x))) 3) *: {mult} x:3 args: y body: (* x y) env: And then we apply the closure to 9...

  31. (let* ((x 3) (let ((x 3)) (y (* x x))) => (let ((y (* x x)) => (* x y)) (* x y))) ((lambda (x) ((lambda (y) (* x y)) (* x x))) 3) *: {mult} x:3 args: y body: (* x y) env: y:9 ...and as before get 27 as the result.

  32. To evaluate: • (letrec ((x1 e1) • (x2 e2) • ... • (xn en)) • e) • in environment E: • 1. build a new frame mapping each xi to *void* • looking up *void* should be an error... • 2. link the frame into E yielding a new environment E’ • 3. evaluate each ei in the new environment E’ to a value vi • 4. set! the bindings in the frame so that xi maps to vi • 5. evaluate the body e in E’

  33. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} 1. create a new frame mapping f to *void*

  34. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} f: *void* 1. create a new frame mapping f to *void* 2. link it in to the environment

  35. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} f: *void* 3. evaluate the expression in the new environment to get a value v.

  36. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: *void* 3. evaluate the expression in the new environment to get a value v.

  37. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: 4. set! the binding in the frame so that f maps to v

  38. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: 5. now evaluate the body of the letrec in the new environment.

  39. (letrec ((f (lambda (x) (if (= 1 x) 1 (* x (f (- 1 x))))))) (f 3)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3

  40. (if (= 1 x) 1 (* x (f (- 1 x)))) => (if (= 1 3) 1 (* x (f (- 1 x)))) => (if #f 1 (* x (f (- 1 x)))) => (* x (f (- 1 x))) => (* 3 (f (- 1 x))) => (* 3 (f 2)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3

  41. (if (= 1 x) 1 (* x (f (- 1 x)))) => (if (= 1 2) 1 (* x (f (- 1 x)))) => (if #f 1 (* x (f (- 1 x)))) => (* x (f (- 1 x))) => (* 2 (f (- 1 x))) => (* 2 (f 1)) *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3 x: 2

  42. (if (= 1 x) 1 (* x (f (- 1 x)))) => (if (= 1 1) 1 (* x (f (- 1 x)))) => (if #t 1 (* x (f (- 1 x)))) => 1 *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3 x: 2 x: 1

  43. (if (= 1 x) 1 (* x (f (- 1 x)))) => (* 2 (f 1)) => (* 2 1) => 2 *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3 x: 2

  44. (if (= 1 x) 1 (* x (f (- 1 x)))) => (* 3 (f 2)) => (* 3 2) => 6 *: {mult} +: {add} =: {equal} -: {sub} args: x body: (if (= 1 x) 1 (* x (f (- 1 x)))) env : f: x: 3

  45. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0))

  46. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0)) f: *void* g: *void*

  47. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0)) f: *void* g: *void*

  48. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0)) args: x body: (g x) env : f: *void* g: *void*

  49. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0)) args: x body: (g x) env : f: *void* g: *void*

  50. (letrec ((f (lambda (x) (g x))) (g (lambda (y) (f y)))) (f 0)) args: x body: (g x) env : f: *void* g: *void* args: y body: (f y) env :

More Related