Subject: Re: CL idiom for Scheme's named let
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 26 Nov 2005 05:25:14 -0600
Newsgroups: comp.lang.lisp
Message-ID: <PpmdneVKmpSH2xXenZ2dnUVZ_tednZ2d@speakeasy.net>
Wade Humeniuk  <whumeniu+anti+spam@telus.net> wrote:
+---------------
| It is/was my undestanding that a invoking the name in a named let
| resulted in a non-conditional jump (with no expectation that the
| jump will return a value). Thus ordinary recursion could not be done.
+---------------

Sorry, that's incorrect. The name in a named LET is bound to an
ordinary Scheme procedure, just as if a LETREC [or LABELS, in CL]
had been used [so that the bound name is visible within the
procedure body]. See R5RS Section 4.2.4 "Iteration":

    "Named let" ... has the same syntax and semantics as ordinary let
    except that <variable> is bound within <body> to a procedure whose
    formal arguments are the bound variables and whose body is <body>.
    Thus the execution of <body> may be repeated by invoking the procedure
    named by <variable>.

That is:

    (let foo ((arg1 init1)
	      ...
	      (argN initN))
      ...body...)

is *identical* to [and in some Scheme implementations may simply
macroexpand to]:

    (letrec ((foo (lambda (arg1 ... argN)
	       ...body...)))
      (foo init1 ...initN))

Or in CL:

    (labels ((foo (arg1 ... argN)
	       ...body...))
      (foo init1 ...initN))

+---------------
| So for the following simple factorial example is invalid:
| (let fact ((n 10))
|     (if (<= n 2) 1 (* n (fact (1- n))))
+---------------

No, that works just fine, once you fix the bug in it!  ;-}  ;-}

    > (let fact ((n 10))
        (if (<= n 1) 1 (* n (fact (1- n)))))
    3628800
    > 

Similarly, multiple self-calls within the body also work:

    > (let fib ((n 10))
	(if (<= n 1) 1 (+ (fib (- n 1)) (fib (- n 2)))))
    89
    > 


-Rob

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