emacs.d/clones/lisp/www.csci.viu.ca/~wesselsd/courses/csci330/code/lisp/lol.cl.html
2022-10-07 19:32:11 +02:00

72 lines
3.1 KiB
HTML

#! /usr/bin/gcl -f
; let over lambda:
; ----------------
; using let blocks that return functions,
; the function returned gives us access to the
; "hidden" local variables in the let block
; effectively making the function an access method
; to private data
; the let block has an internal counter, i, initialized to 0
; the return value from the let block is a function
; whose purpose is to increment the counter
; here we're setting upd to this returned function
(setf upd (let ((i 0)) (lambda () (incf i))))
; each time we call the function (through variable upd)
; it increments the "hidden" counter
(format t "calling (upd): ~A~%" (funcall upd))
(format t " and again: ~A~%" (funcall upd))
(format t " and again: ~A~%" (funcall upd))
(format t " and again: ~A~%" (funcall upd))
; applying let over lambda to create and manipulate objects
; ---------------------------------------------------------
; the pointBuilder initializes and x,y point at 0,0
; and return a function that allows the user to
; move the point around the x,y plane
(defun pointBuilder ()
(let ; initialize the point's location
((x 0) (y 0))
; the lambda function allows the user to supply commands to:
; get the point's current coordinates
; move the point a certain amount in the x,y plane
; jump the point to specific new coordinates
; supply a command to return the current coordinates,
(lambda (command &optional (xval 0) (yval 0))
(cond
((equalp command 'move)
(progn (setf x (+ x xval)) (setf y (+ y yval)) (list x y)))
((equalp command 'jump)
(progn (setf x xval) (setf y yval) (list x y)))
((equalp command 'get)
(list x y))
(t (progn (format t "Invalid command ~A~%" command) (list x y)))
))))
; try out the point manipulator on a couple of points
(format t "~%Working on pointBuilder example~%")
(setf p1 (pointBuilder))
(setf p2 (pointBuilder))
(format t "p1 current location: ~A~%" (funcall p1 'get))
(format t "p2 current location: ~A~%" (funcall p2 'get))
(format t "p1 new location: ~A~%" (funcall p1 'move 3 10))
(format t "p1 new location: ~A~%" (funcall p1 'move 2 -1))
(format t "p2 new location: ~A~%" (funcall p2 'jump -3 4))
; --- Why it works ---
; lisp actually allocates lists on the heap,
; list variables and parameters are really just references into the heap
; lisp keeps track of whether lists are being referenced or not,
; and doesn't reclaim their heap space until they are no longer referenced by anything
; parameter lists and local variable lists (in let blocks)
; are themselves just lists, referenced from the stack for the active function
; the lambda functions above reference the lists of parameters/local variables,
; hence even when the "constructor" function ends, the heap space for
; those lists is not released, effectively giving the lambda functions
; sole access to a private chunk of the heap
; (when the lambda functions go out of scope the heap space is reclaimed)