Subject: Re: how to define a local function
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 14 Apr 2007 04:01:16 -0500
Newsgroups: comp.lang.lisp
Message-ID: <e-OdncW3beLBBb3bnZ2dnUVZ_tqnnZ2d@speakeasy.net>
Pascal Costanza  <pc@p-cos.net> wrote:
+---------------
| Rob Warnock wrote:
| > In Scheme, this is legal:
| >     > (letrec ((a (lambda (x) (+ x 3))))
| > 	(let ((old-a-result (a 2)))
| > 	  (set! a (lambda (x) (+ x 17)))
| > 	  (list old-a-result (a 2))))
| > 
| >     (5 19)
| >     >
| > The same [well, ignoring SET! vs SETF] wouldn't work with
| > your dual value/function LETREC [you get (5 5)], 
| 
| No, I really get the "correct" result:
|  > (defmacro letrec ((&rest bindings) &body body)
|      `(macrolet ,(loop for (var) in bindings
|                        collect `(,var (&rest args)
|                                    `(funcall ,',var ,@args)))
|         (let ,(mapcar #'first bindings)
|           (setq ,@(mapcan #'copy-list bindings))
|           ,@body)))
| 
|  > (letrec ((a (lambda (x) (+ x 3))))
|      (let ((old-a-result (a 2)))
|        (setq a (lambda (x) (+ x 17)))
|        (list old-a-result (a 2))))
| (5 19)
+---------------

*OOPS!!*  Right you are!! My most abject apologies!! I'm
afraid I only skimmed your LETREC macro the first time
I saw it, and somehow totally missed the embedded FUNCALL!
[I somehow misread it as a set of FLETs parallel to the LETs.]
Of *course* it works "correctly"!

"Never mind..."  (*blush*)


-Rob

p.s. That MACRLOET expanding to a FUNCALL of a variable
[maybe a global, maybe a local] is a clever trick. I'm
going to remember that one. I can think of a bunch of
other situations in which to use it...

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607