;; Here is a simple example of a let statement > (let ((x 3) (y 4) (z 5)) (+ x y z)) 12 ;; In this case, it doesn't know what "x" is when defining y > (let ((x 3) (y (+ x 1))) (+ x y)) reference to undefined identifier: x ;; One way out would be to nest the let statements > (let ((x 3)) (let ((y (+ x 1))) (+ x y))) 7 ;; The other way is to use a let* > (let* ((x 3) (y (+ x 1))) (+ x y)) 7 ;; ------------- ;; on closures... ;; Here, it takes the context of x from the containing let > (let ((x 3)) (let ((f (lambda (y) (+ x y)))) (f 1))) 4 ;; But it's possible to return f -- so where does the value of x come from? > (let ((x 3)) (let ((f (lambda (y) (+ x y)))) f)) (lambda (a1) ...) ;; Here we just define that lambda to be g, and we see that we can ;; apply it successfully -- this is because g is a closure, and stores ;; the bits of the defining environment it needs to evaluate g later ;; (in this case, it keeps track that x is 3) > (define g (let ((x 3)) (let ((f (lambda (y) (+ x y)))) f))) > g (lambda (a1) ...) > (g 1) 4 ;; Note that it only keeps track that x is 3 when calling g, not ;; all the time! > x reference to undefined identifier: x >