[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Continuation examples (was Re: So, what the heck is a continuation anyway?)

Guy Steele - Sun Microsystems Labs <gls@labean.East.Sun.COM> writes:

> Okay, just for fun, I upgraded the toy "FOO interpreter" of my
> previous messages:

Hello Guy, nice program :-)

> 	((eq (first exp) 'LETREC)
> 	 (let ((newenv (pairlis (mapcar #'first (second exp))
> 				(make-list (length (second exp)))
> 				env)))
> 	   (@evletrec (second exp) newenv (third exp) newenv cont)))


> (defun @evletrec (bindings slots body env cont)
>   (cond ((null bindings) (@eval body env cont))
> 	(t (@eval (second (first bindings)) env
> 		  #'(lambda (fn)
> 		      (rplacd (first slots) fn)  ;the side effect that "ties the knot"
> 		      (@evletrec (rest bindings) (rest slots) body env cont))))))

There's a bug here: evletrec assumes `slots' will be in the same order
as `bindings', but `pairlis' can muck that up. On my computer with
CLISP, the slots get reversed and the "evil" program becomes
_diabolical_ (`last' is invoked first).

Can be fixed by changing the `pairlis' in @eval to `pairlis-forward':

  (defun pairlis-forward (keys values alist)
    (append (mapcar #'cons keys values) alist))

> The lessons here are:
> (1) LETREC is not that difficult to add.
> (2) Even toy, throwaway interpreters are vulnerable to feature creep.

(3) Even toy, throwaway interpreters have to be ported.