mac (01/22/83)
; The following is a LISP macro which can be used to construct circular ; and otherwise tangled list structures, without a lot of rplacas & ; replacds. It's somewhat like the LET REC of ISWIM. ; ; Such a construct is described in Morris & Schwarz, "Computing Cyclic ; List Structures", in the 1980 LISP conference. ; It has the restriction that the results must be cons cells, not atoms. ; ; This construct is more useful in SCHEME, where it can replace the LABELS ; construct for defining (mutually) recursive functions. It's convenient ; in that it's not restricted to defining lambda expressions. ; ; (fix ((a1 e1) ... (an en)) e) ; ; is like LET except that the e[i] may refer to the a[i] in restricted ways. ; the references are patched up with (replace). ; e.g. ; (fix ((x (cons 'atom x))) x) ; constructs a circular list of 'atom ; (fix ((loop (list 'cond ; constructs a loop ; '(done result) ; (list 't ; '(do-something) ; loop ; ) ) ) ; (fun (list 'lambda () loop)) ; ) ; (fun) ; ... and executes it ; ) ; (fix ((a1 e1) ... (an en)) e0) ; is ; ((lambda (a1 ... an) ; bind the names to cells ; (progn ; (replace a1 v1) ... (replace an vn) ; update the assignments ; e0) ; (list()) ... (list())) (def fix (macro (fix-form) (let* ((bindings (cadr fix-form)) ; binding list (e0-list (cddr fix-form)) ; (list e0) (a-s (mapcar (function car) bindings)) ; names to bind (cell-s (mapcar (function ; blank cells (lambda (a-e) '(list nil))) bindings )) (replace-list (mapcar (function (lambda (a-e) (cons 'replace a-e))) bindings )) (l-form (cons 'lambda (list a-s (cons 'progn (append replace-list e0-list ))))) (new-form (cons l-form cell-s)) ) new-form )))