;; This demo follows examples from ;; https://hbr.github.io/Lambda-Calculus/lambda2/lambda.html ;; (,) x y := \ f := f x y (setq pair (lambda (x y) (lambda (f) (funcall f x y)))) (closure (t) (x y) #'(lambda (f) (funcall f x y))) ;; first p := p K (setq ab (funcall pair 'a 'b)) (closure ((y . b) (x . a)) (f) (funcall f x y)) (setq K (lambda (x y) x)) (closure (t) (x y) x) (setq KI (lambda (x y) y)) (closure (t) (x y) y) (funcall ab K) a (funcall ab KI) b (defmacro dis (f) `(disassemble-internal ,f 2 nil)) dis ;; The disassembly shows that pair is a form of storage: the ab closure ;; as an object saved copies of a and b is its constants vector ("closed ;; over" a and b).There these copies will stay until ab is alive. ;; However, to be of any use these copies need to be accessible. ;; Hence the need for the function f, which alone can access these copies. (dis ab) doc: ... args: (arg1) ; the accessor function f 0 dup 1 constant a ; <<-- closed over a 2 constant b ; <<-- closed over b 3 call 2 4 return nil pair (closure (t) (x y) #'(lambda (f) (funcall f x y))) ;; This function makes functions that close (dis pair) doc: ... args: (arg1 arg2) ; [arg2 arg1] 0 constant make-closure ; [make-closure arg2 arg1] 1 constant ; [ make-closure arg2 arg1] doc: ... ; this is the code of lambda args: (arg1) ; [arg1] 0 dup ; [arg1 arg1] 1 constant V1 ; [v0 v1 arg1 arg1] 2 constant V0 3 call 2 ; [f(v1 v0) arg1] 4 return 2 stack-ref 2 ; [arg2 make-closure arg2 arg1] 3 stack-ref 4 ; [arg1 arg2 make-closure arg2 arg1] 4 call 3 ; [(make-closure arg2 arg1) arg2 arg1] 5 return nil ;; Now we have storage and structure and can build cons cells, structs, trees, etc.