[net.sources] LISP fix macro

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
	       )))