From: Tamas
Subject: how to define a local function
Date: 
Message-ID: <1176307972.212503.151470@y80g2000hsf.googlegroups.com>
I want to define a short function to be locally used inside another
function (it uses arguments of the function, and is a convenient
shorthand for an operation).  It is not useful anywhere else, and my
understanding is that if I used defun inside the function, it would
still pollute the global namespace.

This is how I would do it in Scheme (inside the function):

(let ((foo (lambda (x) (+ 1 x))))
  (foo 2))

If I try to do this in Lisp, I get an error message.  I have a vague
idea that this is caused by functions and variables being in different
namespaces, but don't know how to make this work in CL.

By the way, is there a way to define a macro locally (ie to make is
visible only inside a function)?

Thanks,

Tamas

From: Zach Beane
Subject: Re: how to define a local function
Date: 
Message-ID: <m3fy76dguf.fsf@unnamed.xach.com>
"Tamas" <······@gmail.com> writes:

> I want to define a short function to be locally used inside another
> function (it uses arguments of the function, and is a convenient
> shorthand for an operation).
[snip]
 
> (let ((foo (lambda (x) (+ 1 x))))
>   (foo 2))

Use FLET:

  (flet ((foo (x) (1+ x)))
    (foo 2))

> By the way, is there a way to define a macro locally (ie to make is
> visible only inside a function)?

Use MACROLET:

  (macrolet ((foo (x)
               `(1+ ,x)))
    (foo 2))

Zach
From: ············@gmail.com
Subject: Re: how to define a local function
Date: 
Message-ID: <1176312044.163033.9650@b75g2000hsg.googlegroups.com>
On Apr 11, 12:19 pm, Zach Beane <····@xach.com> wrote:
> "Tamas" <······@gmail.com> writes:
> > I want to define a short function to be locally used inside another
> > function (it uses arguments of the function, and is a convenient
> > shorthand for an operation).
>
> [snip]
>
> > (let ((foo (lambda (x) (+ 1 x))))
> >   (foo 2))
>
> Use FLET:
>
>   (flet ((foo (x) (1+ x)))
>     (foo 2))
>
> > By the way, is there a way to define a macro locally (ie to make is
> > visible only inside a function)?
>
> Use MACROLET:
>
>   (macrolet ((foo (x)
>                `(1+ ,x)))
>     (foo 2))
>
> Zach

Also look at LABELS which will allow you to define recursive local
functions.

Andrew
From: Ari Johnson
Subject: Re: how to define a local function
Date: 
Message-ID: <m2irc2bz0h.fsf@hermes.theari.com>
Zach Beane <····@xach.com> writes:

> "Tamas" <······@gmail.com> writes:
>
>> I want to define a short function to be locally used inside another
>> function (it uses arguments of the function, and is a convenient
>> shorthand for an operation).
> [snip]
>  
>> (let ((foo (lambda (x) (+ 1 x))))
>>   (foo 2))
>
> Use FLET:
>
>   (flet ((foo (x) (1+ x)))
>     (foo 2))
>
>> By the way, is there a way to define a macro locally (ie to make is
>> visible only inside a function)?
>
> Use MACROLET:
>
>   (macrolet ((foo (x)
>                `(1+ ,x)))
>     (foo 2))
>
> Zach

To be complete, LABELS should be mentioned.  There is a difference
between it and FLET that is important to know.

From http://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm :

labels is equivalent to flet except that the scope of the defined function
names for labels encompasses the function definitions themselves as well
as the body.

In other words, if your local functions have to call themselves or each
other, use LABELS.  Otherwise, use FLET.
From: ······@gmail.com
Subject: Re: how to define a local function
Date: 
Message-ID: <1176323858.448527.155390@e65g2000hsc.googlegroups.com>
On Apr 11, 12:29 pm, Ari Johnson <·········@gmail.com> wrote:
> Zach Beane <····@xach.com> writes:
> > "Tamas" <······@gmail.com> writes:
>
> >> I want to define a short function to be locally used inside another
> >> function (it uses arguments of the function, and is a convenient
> >> shorthand for an operation).
> > [snip]
>
> >> (let ((foo (lambda (x) (+ 1 x))))
> >>   (foo 2))
>
> > Use FLET:
>
> >   (flet ((foo (x) (1+ x)))
> >     (foo 2))
>
> >> By the way, is there a way to define a macro locally (ie to make is
> >> visible only inside a function)?
>
> > Use MACROLET:
>
> >   (macrolet ((foo (x)
> >                `(1+ ,x)))
> >     (foo 2))
>
> > Zach
>
> To be complete, LABELS should be mentioned.  There is a difference
> between it and FLET that is important to know.
>
> Fromhttp://www.lispworks.com/documentation/HyperSpec/Body/s_flet_.htm:
>
> labels is equivalent to flet except that the scope of the defined function
> names for labels encompasses the function definitions themselves as well
> as the body.
>
> In other words, if your local functions have to call themselves or each
> other, use LABELS.  Otherwise, use FLET.

Maybe I'm missing something, but is there a reason to not just always
use labels?  In a non-recursive definition, what does flet buy you
over labels?
From: Kaz Kylheku
Subject: Re: how to define a local function
Date: 
Message-ID: <1176327130.860550.180600@o5g2000hsb.googlegroups.com>
On Apr 11, 1:37 pm, ·······@gmail.com" <······@gmail.com> wrote:
> Maybe I'm missing something, but is there a reason to not just always
> use labels?  In a non-recursive definition, what does flet buy you
> over labels?

What FLET buys you is that even if a function X has a body which calls
function X, that definition is /still/ not recursive.

This allows you to write an inner wrapper function X for some outer
function X.
From: Barry Margolin
Subject: Re: how to define a local function
Date: 
Message-ID: <barmar-6C5995.22113311042007@comcast.dca.giganews.com>
In article <························@o5g2000hsb.googlegroups.com>,
 "Kaz Kylheku" <········@gmail.com> wrote:

> On Apr 11, 1:37 pm, ·······@gmail.com" <······@gmail.com> wrote:
> > Maybe I'm missing something, but is there a reason to not just always
> > use labels?  In a non-recursive definition, what does flet buy you
> > over labels?
> 
> What FLET buys you is that even if a function X has a body which calls
> function X, that definition is /still/ not recursive.
> 
> This allows you to write an inner wrapper function X for some outer
> function X.

Also, the difference can be helpful to human readers.  LABELS tells them 
to be on the lookout for recursion, FLET means it isn't.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Edi Weitz
Subject: Re: how to define a local function
Date: 
Message-ID: <uy7ky1508.fsf@agharta.de>
On Wed, 11 Apr 2007 22:11:33 -0400, Barry Margolin <······@alum.mit.edu> wrote:

> Also, the difference can be helpful to human readers.  LABELS tells
> them to be on the lookout for recursion, FLET means it isn't.

Sorry for being picky, but it doesn't have to be recursion.  It could
just be something like

  (labels ((foo (x) ...)
           (bar (y) ...)
           (quux (x y)
             (do-something (foo x) (bar y))))
    ...)

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: jayessay
Subject: Re: how to define a local function
Date: 
Message-ID: <m3wt0hfpff.fsf@sirius.goldenthreadtech.com>
Edi Weitz <········@agharta.de> writes:

> On Wed, 11 Apr 2007 22:11:33 -0400, Barry Margolin <······@alum.mit.edu> wrote:
> 
> > Also, the difference can be helpful to human readers.  LABELS tells
> > them to be on the lookout for recursion, FLET means it isn't.
> 
> Sorry for being picky, but it doesn't have to be recursion.  It could
> just be something like
> 
>   (labels ((foo (x) ...)
>            (bar (y) ...)
>            (quux (x y)
>              (do-something (foo x) (bar y))))
>     ...)

Does anyone remember the historical (or other) reason for why _labels_
is called "labels"?  It always seemed that the most likely name would
have been flet* (the above usage is particularly indicative of this in
comparison with let and let*).  Just curious, as I've never seen this
"explained"...


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Zach Beane
Subject: Re: how to define a local function
Date: 
Message-ID: <m3y7kxbhhk.fsf@unnamed.xach.com>
jayessay <······@foo.com> writes:

> Edi Weitz <········@agharta.de> writes:
> 
> > On Wed, 11 Apr 2007 22:11:33 -0400, Barry Margolin
> > <······@alum.mit.edu> wrote:
> > 
> > > Also, the difference can be helpful to human readers.  LABELS tells
> > > them to be on the lookout for recursion, FLET means it isn't.
> > 
> > Sorry for being picky, but it doesn't have to be recursion.  It could
> > just be something like
> > 
> >   (labels ((foo (x) ...)
> >            (bar (y) ...)
> >            (quux (x y)
> >              (do-something (foo x) (bar y))))
> >     ...)
> 
> Does anyone remember the historical (or other) reason for why _labels_
> is called "labels"?  It always seemed that the most likely name would
> have been flet* (the above usage is particularly indicative of this in
> comparison with let and let*).  Just curious, as I've never seen this
> "explained"...

My turn to be picky. LABELS has an important difference from LET*: a
LET* variable binding can refer only to preceding bindings, while
LABELS can refer to any function binding, before or after, in the
group.

Zach
From: jayessay
Subject: Re: how to define a local function
Date: 
Message-ID: <m3slb5fob2.fsf@sirius.goldenthreadtech.com>
Zach Beane <····@xach.com> writes:

> jayessay <······@foo.com> writes:
> 
> > Edi Weitz <········@agharta.de> writes:
> > 
> > > On Wed, 11 Apr 2007 22:11:33 -0400, Barry Margolin
> > > <······@alum.mit.edu> wrote:
> > > 
> > > > Also, the difference can be helpful to human readers.  LABELS tells
> > > > them to be on the lookout for recursion, FLET means it isn't.
> > > 
> > > Sorry for being picky, but it doesn't have to be recursion.  It could
> > > just be something like
> > > 
> > >   (labels ((foo (x) ...)
> > >            (bar (y) ...)
> > >            (quux (x y)
> > >              (do-something (foo x) (bar y))))
> > >     ...)
> > 
> > Does anyone remember the historical (or other) reason for why _labels_
> > is called "labels"?  It always seemed that the most likely name would
> > have been flet* (the above usage is particularly indicative of this in
> > comparison with let and let*).  Just curious, as I've never seen this
> > "explained"...
> 
> My turn to be picky. LABELS has an important difference from LET*: a
> LET* variable binding can refer only to preceding bindings, while
> LABELS can refer to any function binding, before or after, in the
> group.

Sure.  Obviously labels is not a direct analog of let* (they are doing
different jobs), but the * in let* doesn't _mean_ the binding
semantics involved only that it is different from let.  So, do you
have any idea about the name???


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <3cadndQ-0ueZe4PbnZ2dnUVZ_gadnZ2d@speakeasy.net>
Zach Beane  <····@xach.com> wrote:
+---------------
| jayessay <······@foo.com> writes:
| > Does anyone remember the historical (or other) reason for why _labels_
| > is called "labels"?  It always seemed that the most likely name would
| > have been flet* (the above usage is particularly indicative of this in
| > comparison with let and let*).  Just curious, as I've never seen this
| > "explained"...
| 
| My turn to be picky. LABELS has an important difference from LET*: a
| LET* variable binding can refer only to preceding bindings, while
| LABELS can refer to any function binding, before or after, in the group.
+---------------

Right. Actually, Scheme gets it right for a Lisp1, with LET/LET*
and LETREC instead of CL's LET/LET*/FLET and LABELS. But LETREC
and LABELS have different syntaxes and semantics. LETREC binds
arbitrary *values*, not functions [though in a Lisp1 a "value"
which is an evaluated LAMBDA expression "is" a function], while
LABELS binds *only* functions, like FLET.

CL *could* have used FLETREC instead of LABELS, I suppose, except
LABELS was already in MacLisp (I think) and predated Scheme.

Note that even with LABELS, CL really has no direct counterpart
for Scheme's LETREC [unless you write a CL macro that expands it
the same way most Schemes do, as a LET that binds all the vars to
NIL first then SETFs them later]. That is, the following works in
Scheme, but there is no standard operator in CL that you can replace
the LETREC with that will work:

    > ((lambda (n)
	 (letrec ((f (lambda (x)
		       (if (<= x 1)
			 1
			 (* x (apply f (- x 1) '()))))))
	   (apply f n '())))
       5)

    120
    > 

[Note: The funny APPLY forms, which work in both Scheme & CL,
are a workaround for FUNCALL per se not existing in Scheme.]


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Barry Margolin
Subject: Re: how to define a local function
Date: 
Message-ID: <barmar-A262D8.22205212042007@comcast.dca.giganews.com>
In article <································@speakeasy.net>,
 ····@rpw3.org (Rob Warnock) wrote:

> Zach Beane  <····@xach.com> wrote:
> +---------------
> | jayessay <······@foo.com> writes:
> | > Does anyone remember the historical (or other) reason for why _labels_
> | > is called "labels"?  It always seemed that the most likely name would
> | > have been flet* (the above usage is particularly indicative of this in
> | > comparison with let and let*).  Just curious, as I've never seen this
> | > "explained"...
> | 
> | My turn to be picky. LABELS has an important difference from LET*: a
> | LET* variable binding can refer only to preceding bindings, while
> | LABELS can refer to any function binding, before or after, in the group.
> +---------------
> 
> Right. Actually, Scheme gets it right for a Lisp1, with LET/LET*
> and LETREC instead of CL's LET/LET*/FLET and LABELS. But LETREC
> and LABELS have different syntaxes and semantics. LETREC binds
> arbitrary *values*, not functions [though in a Lisp1 a "value"
> which is an evaluated LAMBDA expression "is" a function], while
> LABELS binds *only* functions, like FLET.

But the difference between LET and LETREC is only significant for the 
function values.  But I suppose you could get cute and have things like:

(letrec ((fun1 (lambda ...))
         (list-of-funs (list (lambda ...)
                             (lambda ...))))
  ...)

fun1 can use ((car list-of-funs) ...).

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <8IGdnTJkD45Ab4PbnZ2dnUVZ_jednZ2d@speakeasy.net>
Barry Margolin  <······@alum.mit.edu> wrote:
+---------------
| ····@rpw3.org (Rob Warnock) wrote:
| > Right. Actually, Scheme gets it right for a Lisp1, with LET/LET*
| > and LETREC instead of CL's LET/LET*/FLET and LABELS. But LETREC
| > and LABELS have different syntaxes and semantics. LETREC binds
| > arbitrary *values*, not functions [though in a Lisp1 a "value"
| > which is an evaluated LAMBDA expression "is" a function], while
| > LABELS binds *only* functions, like FLET.
| 
| But the difference between LET and LETREC is only significant for the 
| function values.  But I suppose you could get cute and have things like:
| 
| (letrec ((fun1 (lambda ...))
|          (list-of-funs (list (lambda ...)
|                              (lambda ...))))
|   ...)
| 
| fun1 can use ((car list-of-funs) ...).
+---------------

Exactly. That doesn't work for any variable-binding construct
built into CL.[1]


-Rob

[1] Though as I noted, one could write a LETREC macro
    in CL that does it the same way Scheme does. The URL
    <http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html>
    has a reference LETREC macro (in Scheme) that could be
    translated to CL fairly easily, I suspect.

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <588qh2F2fsupvU1@mid.individual.net>
Rob Warnock wrote:
> Barry Margolin  <······@alum.mit.edu> wrote:
> +---------------
> | ····@rpw3.org (Rob Warnock) wrote:
> | > Right. Actually, Scheme gets it right for a Lisp1, with LET/LET*
> | > and LETREC instead of CL's LET/LET*/FLET and LABELS. But LETREC
> | > and LABELS have different syntaxes and semantics. LETREC binds
> | > arbitrary *values*, not functions [though in a Lisp1 a "value"
> | > which is an evaluated LAMBDA expression "is" a function], while
> | > LABELS binds *only* functions, like FLET.
> | 
> | But the difference between LET and LETREC is only significant for the 
> | function values.  But I suppose you could get cute and have things like:
> | 
> | (letrec ((fun1 (lambda ...))
> |          (list-of-funs (list (lambda ...)
> |                              (lambda ...))))
> |   ...)
> | 
> | fun1 can use ((car list-of-funs) ...).
> +---------------
> 
> Exactly. That doesn't work for any variable-binding construct
> built into CL.[1]
> 
> 
> -Rob
> 
> [1] Though as I noted, one could write a LETREC macro
>     in CL that does it the same way Scheme does. The URL
>     <http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html>
>     has a reference LETREC macro (in Scheme) that could be
>     translated to CL fairly easily, I suspect.

The macro over there tries to remain applicative and keep the order of 
evaluation unspecified. If you can afford to be less picky, letrec is 
quite straightforward to implement:

(defmacro letrec ((&rest bindings) &body body)
   `(let ,(mapcar #'first bindings)
      (setq ,@(mapcan #'copy-list bindings))
      ,@body))

((lambda (n)
    (letrec ((f (lambda (x)
                  (if (<= x 1)
                    1
                    (* x (funcall f (- x 1)))))))
      (funcall f n)))
  5)

If you want to see the bindings in both function and variable 
namespaces, you can easily do the following as well:

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

Now you can say this:

((lambda (n)
    (letrec ((f (lambda (x)
                  (if (<= x 1)
                    1
                    (* x (f (- x 1)))))))
      (f n)))
  5)


...just like in Scheme. ;)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <kKidnRtTw5JTpYLbnZ2dnUVZ_ompnZ2d@speakeasy.net>
Pascal Costanza  <··@p-cos.net> wrote:
+---------------
| Rob Warnock wrote:
| > [1] Though as I noted, one could write a LETREC macro
| >     in CL that does it the same way Scheme does. The URL
| >     <http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html>
| >     has a reference LETREC macro (in Scheme) that could be
| >     translated to CL fairly easily, I suspect.
| 
| The macro over there tries to remain applicative and keep the order of 
| evaluation unspecified. If you can afford to be less picky, letrec is 
| quite straightforward to implement:
| 
| (defmacro letrec ((&rest bindings) &body body)
|    `(let ,(mapcar #'first bindings)
|       (setq ,@(mapcan #'copy-list bindings))
|       ,@body))
+---------------

Just so, thank you. With that added to one's CL environment,
my original version then works -- unmodified -- in *either*
Scheme or CL:

    > (defmacro letrec ((&rest bindings) &body body)
        `(let ,(mapcar #'first bindings)
           (setq ,@(mapcan #'copy-list bindings))
           ,@body))

    LETREC
    > ((lambda (n)
	 (letrec ((f (lambda (x)
		       (if (<= x 1)
			 1
			 (* x (apply f (- x 1) '()))))))
	   (apply f n '())))
       5)

    120
    > 

+---------------
| If you want to see the bindings in both function and variable 
| namespaces, you can easily do the following as well:
+---------------

But then you would get inconsistences between the Scheme & CL
versions if there were ever an assignment to one of the variables.
So, thank you, but no thank you.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <588v9eF2flg76U1@mid.individual.net>
Rob Warnock wrote:
> Pascal Costanza  <··@p-cos.net> wrote:
> +---------------
> | Rob Warnock wrote:
> | > [1] Though as I noted, one could write a LETREC macro
> | >     in CL that does it the same way Scheme does. The URL
> | >     <http://schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-10.html>
> | >     has a reference LETREC macro (in Scheme) that could be
> | >     translated to CL fairly easily, I suspect.
> | 
> | The macro over there tries to remain applicative and keep the order of 
> | evaluation unspecified. If you can afford to be less picky, letrec is 
> | quite straightforward to implement:
> | 
> | (defmacro letrec ((&rest bindings) &body body)
> |    `(let ,(mapcar #'first bindings)
> |       (setq ,@(mapcan #'copy-list bindings))
> |       ,@body))
> +---------------
> 
> Just so, thank you. With that added to one's CL environment,
> my original version then works -- unmodified -- in *either*
> Scheme or CL:
[...]

Right.

> +---------------
> | If you want to see the bindings in both function and variable 
> | namespaces, you can easily do the following as well:
> +---------------
> 
> But then you would get inconsistences between the Scheme & CL
> versions if there were ever an assignment to one of the variables.

I don't think there would be any inconsistencies. Note that I have 
defined macros for the function namespace, so any assignment to the 
variables would be respected.

Do you have something else in mind?


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <YZadnabA6aHptr3bnZ2dnUVZ_s2vnZ2d@speakeasy.net>
Pascal Costanza  <··@p-cos.net> wrote:
+---------------
| Rob Warnock wrote:
| > Pascal Costanza  <··@p-cos.net> wrote:
| > +---------------
| > | If you want to see the bindings in both function and variable 
| > | namespaces, you can easily do the following as well:
| > +---------------
| > 
| > But then you would get inconsistences between the Scheme & CL
| > versions if there were ever an assignment to one of the variables.
| 
| I don't think there would be any inconsistencies. Note that I have 
| defined macros for the function namespace, so any assignment to the 
| variables would be respected.
+---------------

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)], since the
SETF would only change the value binding, but *would* work
with a values-only LETREC if one referenced the bound function
values *only* with FUNCALL (or my APPLY idiom).

Anyway, it's not a biggy... Lisp1 & LispN are too far apart
to merge with simple hacks like that anyway.

Summary/recap/call-for-end-of-thread: I was just trying to
point out that even though CL's LABELS *does* provide the same
self- & mutually-recursive bindings for fuctions that Scheme's
LETREC does for functions, for value bindings CL *doesn't*
have a direct native equivalent... but that an equivalent macro
could be defined [which you demonstrated, thanks].


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <58bbjdF2ge02qU1@mid.individual.net>
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)

> since the
> SETF would only change the value binding, but *would* work
> with a values-only LETREC if one referenced the bound function
> values *only* with FUNCALL (or my APPLY idiom).

That's what my version above effectively does.

> Anyway, it's not a biggy... Lisp1 & LispN are too far apart
> to merge with simple hacks like that anyway.

No, it's actually very straightforward to embed Lisp-1 functionality in 
a Lisp-2, as I have shown above.

> Summary/recap/call-for-end-of-thread: I was just trying to
> point out that even though CL's LABELS *does* provide the same
> self- & mutually-recursive bindings for fuctions that Scheme's
> LETREC does for functions, for value bindings CL *doesn't*
> have a direct native equivalent...

Sure.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <e-OdncW3beLBBb3bnZ2dnUVZ_tqnnZ2d@speakeasy.net>
Pascal Costanza  <··@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.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <58fbsvF2glr4mU1@mid.individual.net>
Rob Warnock wrote:
> Pascal Costanza  <··@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*)

No problem. ;)

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

Yes, that's the essential part why one can rightfully claim that a 
Lisp-1 can easily be embedded in a Lisp-N.

I don't see a straightforward way to do something similar the other way 
around, though.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: szergling
Subject: Re: how to define a local function
Date: 
Message-ID: <1176773628.603625.261060@e65g2000hsc.googlegroups.com>
Howdy folks,

This thread has reminded me of an itch I've been scratching, that
unfortunately, I still haven't solved. It all started with this:

fibs :: [Integer]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

Or for a more lispy translation:

(let ((fibs (cons 0 (cons 1 (mapcar #'+ fibs (cdr fibs))))))
  ...do something...)

where we want the hypothetical cons and let (or perhaps more
accurately something like the hypothetical letrec) to be lazy.

I thought I would do something similar, so here's a quick
hack. Unfortunately, it ended up only working with circular
structures... I feel that it's not quite enough. Additionally, it's
buggy -> in the macro, we shouldn't use nsubstitute-all twice, as it
does different things each time. It should really be a code-walker the
first time round, and a object/structure walker the second time round
(one does code, the other data).

I have not really gained much on top of reader macros, but at least
this is an alternative to using reader macros. It feels like it should
be useful (when debugged), but for what? Any ideas?

(defun nsubstitute-all (new old structure &key (test 'equal))
  ;; this needs to know how to walk all structures. test must also be
  ;; quite general - we will be testing with different ie
  ;; heterogeneous types, so perhaps it must always be #'equal.
  (labels ((helper (structure)
             (typecase structure
               (cons (if (funcall test (car structure) old)
                         (setf (car structure) new)
                         (helper (car structure)))
                     (if (funcall test (cdr structure) old)
                         (setf (cdr structure) new)
                         (helper (cdr structure)))))))
    (helper structure)
    structure))

(defmacro letrec ((var val) &body body)
  (with-unique-names (placeholder)
    `(let* ((,var ,(nsubstitute-all `',placeholder var (copy-tree
val))))
      (setf ,var (nsubstitute-all ,var ',placeholder ,var))
      ,@body)))

(setf *print-circle* t) ;; You need this

(letrec (x (cons 1 (cons 2 x))) x)
#1=(1 2 . #1#)

(letrec (x (list 1 2 x 3 4))  x)
#1=(1 2 #1# 3 4)

By the way, I don't think the Series package can do this. Can anyone
who know more about that maybe show me a few tricks? I would like to
read some samples of source code (useful instructive code snippets
would be just as good) that use the Series package to good effect.

RANT

Common Lispers just like to show the classic delay and force macro, as
if delayed evaluation is a fait accompli. They usually quote some
variant of the 'On Lisp' example...

(defconstant unforced (gensym))
(defstruct delay  forced closure)
(defmacro delay (expr)
  (let ((self (gensym)))
    `(let ((,self (make-delay :forced unforced)))
       (setf (delay-closure ,self)
             #'(lambda ()
                 (setf (delay-forced ,self) ,expr)))
       ,self)))
(defun force (x)
  (if (delay-p x)
      (if (eq (delay-forced x) unforced)
          (funcall (delay-closure x))
          (delay-forced x))
      x))

But it is not quite enough, as there's a lot of work to do
still. Typically, one needs to go through all Common Lisp functions,
and rewrite them as *macros*. Otherwise, there's no way to delay
evaluation in standard funcall (so much for first class
functions). Alternatively, you'll need to write an interpreter -> I've
not personally gone too far down this path, but it looks like you'll
need to rewrite all functions too. Then again, there's probably only a
few hundred function... I just think that maybe something more
powerful is needed, like datapath macros...

http://www2.parc.com/csl/groups/sda/publications/papers/Kiczales-Macros91/for-web.pdf

whichever way, copying Haskell with Common Lisp is not as straight
forward as it may appear at first.

PS: Apologies in advance if this got double-posted.
From: szergling
Subject: Re: how to define a local function
Date: 
Message-ID: <1176774571.122388.252320@n59g2000hsh.googlegroups.com>
> buggy -> in the macro, we shouldn't use nsubstitute-all twice, as it
> does different things each time. It should really be a code-walker the
> first time round, and a object/structure walker the second time round
> (one does code, the other data).
>
> I have not really gained much on top of reader macros, but at least
> this is an alternative to using reader macros. It feels like it should
> be useful (when debugged), but for what? Any ideas?
>
> (defun nsubstitute-all (new old structure &key (test 'equal))
>   ;; this needs to know how to walk all structures. test must also be
>   ;; quite general - we will be testing with different ie
>   ;; heterogeneous types, so perhaps it must always be #'equal.
>   (labels ((helper (structure)
>              (typecase structure
>                (cons (if (funcall test (car structure) old)
>                          (setf (car structure) new)
>                          (helper (car structure)))
>                      (if (funcall test (cdr structure) old)
>                          (setf (cdr structure) new)
>                          (helper (cdr structure)))))))
>     (helper structure)
>     structure))
>
> (defmacro letrec ((var val) &body body)
>   (with-unique-names (placeholder)
>     `(let* ((,var ,(nsubstitute-all `',placeholder var (copy-tree
> val))))
>       (setf ,var (nsubstitute-all ,var ',placeholder ,var))
>       ,@body)))
>
> (setf *print-circle* t) ;; You need this
>
> (letrec (x (cons 1 (cons 2 x))) x)
> #1=(1 2 . #1#)
>
> (letrec (x (list 1 2 x 3 4))  x)
> #1=(1 2 #1# 3 4)
>


Oopsies, some improvements - there's no need for a code-walker, just
an object
walker. Come to think of it, the object walker won't be portable - it
might not even be possible when it comes to things like closures... we
might have to stick to reader macros.

(defmacro letrec ((var val) &body body)
  (with-unique-names (placeholder)
    `(let* ((,var
             (let ((,var ',placeholder))
               ,val)))
       (setf ,var (nsubstitute-all ,var ',placeholder ,var))
       ,@body)))

(defun nsubstitute-all (new old structure &key (test 'equal))
  ;; this needs to know how to walk all structures. test must also be
  ;; quite general - we will be testing with different ie
  ;; heterogeneous types, so perhaps it must always be #'equal.
  (labels ((helper (structure)
             (macrolet ((cond-replace (place)
                          `(if (funcall test ,place old)
                               (setf ,place new)
                               (helper ,place))))
               (typecase structure
                 (cons (cond-replace (car structure))
                       (cond-replace (cdr structure)))))))
    (helper structure)
    structure))
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <58j9u6F2e50ofU1@mid.individual.net>
szergling wrote:

> RANT
> 
> Common Lispers just like to show the classic delay and force macro, as
> if delayed evaluation is a fait accompli. They usually quote some
> variant of the 'On Lisp' example...
> 
> (defconstant unforced (gensym))
> (defstruct delay  forced closure)
> (defmacro delay (expr)
>   (let ((self (gensym)))
>     `(let ((,self (make-delay :forced unforced)))
>        (setf (delay-closure ,self)
>              #'(lambda ()
>                  (setf (delay-forced ,self) ,expr)))
>        ,self)))
> (defun force (x)
>   (if (delay-p x)
>       (if (eq (delay-forced x) unforced)
>           (funcall (delay-closure x))
>           (delay-forced x))
>       x))

It doesn't see to me that delay and force are too useful. They are 
typically just used to illustrate what macros can do. For practical 
purposes, I don't think they are very practical. ;) (Even R6RS Scheme 
drops them.)

> But it is not quite enough, as there's a lot of work to do
> still. Typically, one needs to go through all Common Lisp functions,
> and rewrite them as *macros*. Otherwise, there's no way to delay
> evaluation in standard funcall (so much for first class
> functions).

No, going through all functions and turning them into delaying ones 
doesn't do the job. You need a distinction between what functions you 
consider to be primitives and what functions you want to be implicitly 
delaying. The "primitive" functions would be the implicitly forcing 
ones. (If no function implicitly forces delayed computation, your 
programs would never ever compute anything. ;)

Because that distinction is important, I think that in practice, it's 
more likely that people tend to use domain-specific variations of lazy 
evaluation.

BTW, it's a nice CLOS MOP exercise to come up with generic function 
classes for implicitly delaying and forcing generic functions.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: szergling
Subject: Re: how to define a local function
Date: 
Message-ID: <1176989834.224716.276980@n59g2000hsh.googlegroups.com>
On Apr 17, 7:05 pm, Pascal Costanza <····@p-cos.net> wrote:
> szergling wrote:

[[ snip ]]

> It doesn't see to me that delay and force are too useful. They are
> typically just used to illustrate what macros can do. For practical
> purposes, I don't think they are very practical. ;) (Even R6RS Scheme
> drops them.)
>
> > But it is not quite enough, as there's a lot of work to do
> > still. Typically, one needs to go through all Common Lisp functions,
> > and rewrite them as *macros*. Otherwise, there's no way to delay
> > evaluation in standard funcall (so much for first class
> > functions).
>
> No, going through all functions and turning them into delaying ones
> doesn't do the job. You need a distinction between what functions you
> consider to be primitives and what functions you want to be implicitly
> delaying. The "primitive" functions would be the implicitly forcing
> ones. (If no function implicitly forces delayed computation, your
> programs would never ever compute anything. ;)

You mean eg, car has to force evaluation, vs cons which is strict in
the first arg? (I'm still fuzzy on strictness, Haskell style).

> Because that distinction is important, I think that in practice, it's
> more likely that people tend to use domain-specific variations of lazy
> evaluation.
>
> BTW, it's a nice CLOS MOP exercise to come up with generic function
> classes for implicitly delaying and forcing generic functions.

Could you quickly elaborate? There doesn't seem to be any escape from
using macros to avoid eager evaluation, and again my pet peeve with
that is losing first class functions. No foldr (I like how laziness
works around the non-tail recursiveness of foldr), no mapcar...
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <58pn3aF2hnbj1U1@mid.individual.net>
szergling wrote:
> On Apr 17, 7:05 pm, Pascal Costanza <····@p-cos.net> wrote:
>> szergling wrote:
> 
> [[ snip ]]
> 
>> It doesn't see to me that delay and force are too useful. They are
>> typically just used to illustrate what macros can do. For practical
>> purposes, I don't think they are very practical. ;) (Even R6RS Scheme
>> drops them.)
>>
>>> But it is not quite enough, as there's a lot of work to do
>>> still. Typically, one needs to go through all Common Lisp functions,
>>> and rewrite them as *macros*. Otherwise, there's no way to delay
>>> evaluation in standard funcall (so much for first class
>>> functions).
>> No, going through all functions and turning them into delaying ones
>> doesn't do the job. You need a distinction between what functions you
>> consider to be primitives and what functions you want to be implicitly
>> delaying. The "primitive" functions would be the implicitly forcing
>> ones. (If no function implicitly forces delayed computation, your
>> programs would never ever compute anything. ;)
> 
> You mean eg, car has to force evaluation, vs cons which is strict in
> the first arg? (I'm still fuzzy on strictness, Haskell style).

I don't know the details of Haskell either. However, it's just the 
simple observations that some operators must be strict, otherwise 
nothing would ever happen, right?

>> Because that distinction is important, I think that in practice, it's
>> more likely that people tend to use domain-specific variations of lazy
>> evaluation.
>>
>> BTW, it's a nice CLOS MOP exercise to come up with generic function
>> classes for implicitly delaying and forcing generic functions.
> 
> Could you quickly elaborate? There doesn't seem to be any escape from
> using macros to avoid eager evaluation, and again my pet peeve with
> that is losing first class functions. No foldr (I like how laziness
> works around the non-tail recursiveness of foldr), no mapcar...

If you want to delay arguments to a function, you're indeed out. In 
Common Lisp, you have to use macros for that. Older Lisp dialects had 
non-evaluating lambda forms (like nlambda or fexprs) for doing this, but 
that's not available in Common Lisp (and in none of its implementations, 
AFAICT).

However, what you can do with the CLOS MOP is to create a function class 
that delays its execution. Roughly like this:

(defclass delayed-function (standard-generic-function) ()
   (:metaclass funcallable-standard-class))

(defmethod compute-discriminating-function ((function delayed-function))
   (let ((discriminating-function (call-next-method)))
     (lambda (&rest args)
       (delay (apply discriminating-function args)))))

Whether that's actually useful is a different question... ;-)


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <588pfeF2fb5ruU1@mid.individual.net>
Rob Warnock wrote:

> Note that even with LABELS, CL really has no direct counterpart
> for Scheme's LETREC [unless you write a CL macro that expands it
> the same way most Schemes do, as a LET that binds all the vars to
> NIL first then SETFs them later]. That is, the following works in
> Scheme, but there is no standard operator in CL that you can replace
> the LETREC with that will work:
> 
>     > ((lambda (n)
> 	 (letrec ((f (lambda (x)
> 		       (if (<= x 1)
> 			 1
> 			 (* x (apply f (- x 1) '()))))))
> 	   (apply f n '())))
>        5)
> 
>     120
>     > 
> 
> [Note: The funny APPLY forms, which work in both Scheme & CL,
> are a workaround for FUNCALL per se not existing in Scheme.]

I think this example doesn't illustrate what you want to say (if I 
understand you correctly).

In Scheme you can just say this:

((lambda (n)
    (letrec ((f (lambda (x)
                  (if (<= x 1)
                    1
                    (* x (f (- x 1)))))))
      (f n)))
  5)

[Note that there is actually no need to use apply here.]

Likewise, you can say that in Common Lisp:

((lambda (n)
    (labels ((f (x)
               (if (<= x 1)
                 1
                 (* x (f (- x 1))))))
      (f n)))
  5)

[No need for funcall either.]


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Rob Warnock
Subject: Re: how to define a local function
Date: 
Message-ID: <VJednV0iD4CeqoLbnZ2dnUVZ_hisnZ2d@speakeasy.net>
Pascal Costanza  <··@p-cos.net> wrote:
+---------------
| Rob Warnock wrote:
| > That is, the following works in
| > Scheme, but there is no standard operator in CL that you can replace
| > the LETREC with that will work:
| >     > ((lambda (n)
| > 	 (letrec ((f (lambda (x)
| > 		       (if (<= x 1)
| > 			 1
| > 			 (* x (apply f (- x 1) '()))))))
| > 	   (apply f n '())))
| >        5)
| >     120
| >     > 
| > 
| > [Note: The funny APPLY forms, which work in both Scheme & CL,
| > are a workaround for FUNCALL per se not existing in Scheme.]
| 
| I think this example doesn't illustrate what you want to say
| (if I understand you correctly).
+---------------

No, I don't think you did understand me correctly, or at least,
not what my real point was. I carefully wrote that example so that
the whole thing *would* work in either Scheme or CL, without any
Lisp1/LispN differences in syntax, without any LET/FLET differences
in syntax, *if only* there existed some form in CL that did LETREC.

But there isn't. [...without adding a LETREC macro.]

+---------------
| In Scheme you can just say this:
...
| [Note that there is actually no need to use apply here.]
| 
| Likewise, you can say that in Common Lisp:
+---------------

Yes, but then the two expressions are *different* -- more
different that just what operator name you use for LETREC/LABELS.
One needs a LAMBDA, the other must *not* have the LAMBDA, etc.
The way I wrote it those differences were masked.


-Rob

-----
Rob Warnock			<····@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607
From: Pascal Costanza
Subject: Re: how to define a local function
Date: 
Message-ID: <588vagF2flg76U2@mid.individual.net>
Rob Warnock wrote:
> Pascal Costanza  <··@p-cos.net> wrote:
> +---------------
> | Rob Warnock wrote:
> | > That is, the following works in
> | > Scheme, but there is no standard operator in CL that you can replace
> | > the LETREC with that will work:
> | >     > ((lambda (n)
> | > 	 (letrec ((f (lambda (x)
> | > 		       (if (<= x 1)
> | > 			 1
> | > 			 (* x (apply f (- x 1) '()))))))
> | > 	   (apply f n '())))
> | >        5)
> | >     120
> | >     > 
> | > 
> | > [Note: The funny APPLY forms, which work in both Scheme & CL,
> | > are a workaround for FUNCALL per se not existing in Scheme.]
> | 
> | I think this example doesn't illustrate what you want to say
> | (if I understand you correctly).
> +---------------
> 
> No, I don't think you did understand me correctly, or at least,
> not what my real point was. I carefully wrote that example so that
> the whole thing *would* work in either Scheme or CL, without any
> Lisp1/LispN differences in syntax, without any LET/FLET differences
> in syntax, *if only* there existed some form in CL that did LETREC.
> 
> But there isn't. [...without adding a LETREC macro.]

Indeed, I missed that part.


Pascal

-- 
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
From: Pascal Bourguignon
Subject: Re: how to define a local function
Date: 
Message-ID: <87bqhskan8.fsf@voyager.informatimago.com>
jayessay <······@foo.com> writes:
> Does anyone remember the historical (or other) reason for why _labels_
> is called "labels"?  It always seemed that the most likely name would
> have been flet* (the above usage is particularly indicative of this in
> comparison with let and let*).  Just curious, as I've never seen this
> "explained"...

In LISP 1.5, there was a LABEL operator to make self-recursive lambdas.

Here is the meta-source of APPLY in LISP 1.5:

       REM APPLY(F,L,A) =
       REM    SELECT(CAR(L).,
       REM           -1,APP2(F,L,A).,
       REM           LAMBDA,EVAL(F,APPEND(PAIR(CADR(F),L),A)).,
       REM           LABEL,APPLY(CADDR(F),L,APPEND(
       REM                PAIR1(CADR(F),CADDR(F))),A).,
       REM           APPLY(EVAL(F,A),L,A))


So you could write IIRC:

(MAPCAR (QUOTE (1 5 10 15))
        (LABEL FACT (X) (IF (LESSP X 1) 1 (TIMES X (FACT (MINUS X))))))

;; Yes, arguments to MAPCAR were in the other order, since it took only one list.

-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: Pascal Bourguignon
Subject: Re: how to define a local function
Date: 
Message-ID: <873b34ka9l.fsf@voyager.informatimago.com>
Pascal Bourguignon <···@informatimago.com> writes:

> jayessay <······@foo.com> writes:
>> Does anyone remember the historical (or other) reason for why _labels_
>> is called "labels"?  It always seemed that the most likely name would
>> have been flet* (the above usage is particularly indicative of this in
>> comparison with let and let*).  Just curious, as I've never seen this
>> "explained"...
>
> In LISP 1.5, there was a LABEL operator to make self-recursive lambdas.
>
> Here is the meta-source of APPLY in LISP 1.5:
>
>        REM APPLY(F,L,A) =
>        REM    SELECT(CAR(L).,
>        REM           -1,APP2(F,L,A).,
>        REM           LAMBDA,EVAL(F,APPEND(PAIR(CADR(F),L),A)).,
>        REM           LABEL,APPLY(CADDR(F),L,APPEND(
>        REM                PAIR1(CADR(F),CADDR(F))),A).,
>        REM           APPLY(EVAL(F,A),L,A))
>
>
> So you could write IIRC:
>
> (MAPCAR (QUOTE (1 5 10 15))
>         (LABEL FACT (X) (IF (LESSP X 1) 1 (TIMES X (FACT (MINUS X))))))
>
> ;; Yes, arguments to MAPCAR were in the other order, since it took only one list.


http://www-formal.stanford.edu/jmc/history/lisp/node3.html

mentions that:

    ... the LABEL notation was invented by Nathaniel Rochester for
    that purpose. D.M.R. Park pointed out that LABEL was logically
    unnecessary since the result could be achieved using only LAMBDA -
    by a construction analogous to Church's Y-operator, albeit in a
    more complicated way.


So there you have the origins of LABELS, which is of course an
evolution allowing to give labels to several possibly inter recursive
functions.

-- 
__Pascal Bourguignon__
http://www.informatimago.com
http://pjb.ogamita.org
From: John Thingstad
Subject: Re: how to define a local function
Date: 
Message-ID: <op.tqpw8ijepqzri1@pandora.upc.no>
On Fri, 13 Apr 2007 09:15:39 +0200, Pascal Bourguignon  
<···@informatimago.com> wrote:

> jayessay <······@foo.com> writes:
>> Does anyone remember the historical (or other) reason for why _labels_
>> is called "labels"?  It always seemed that the most likely name would
>> have been flet* (the above usage is particularly indicative of this in
>> comparison with let and let*).  Just curious, as I've never seen this
>> "explained"...
>
> In LISP 1.5, there was a LABEL operator to make self-recursive lambdas.
>
> Here is the meta-source of APPLY in LISP 1.5:
>
>        REM APPLY(F,L,A) =
>        REM    SELECT(CAR(L).,
>        REM           -1,APP2(F,L,A).,
>        REM           LAMBDA,EVAL(F,APPEND(PAIR(CADR(F),L),A)).,
>        REM           LABEL,APPLY(CADDR(F),L,APPEND(
>        REM                PAIR1(CADR(F),CADDR(F))),A).,
>        REM           APPLY(EVAL(F,A),L,A))
>
>
> So you could write IIRC:
>
> (MAPCAR (QUOTE (1 5 10 15))
>         (LABEL FACT (X) (IF (LESSP X 1) 1 (TIMES X (FACT (MINUS X))))))
>
> ;; Yes, arguments to MAPCAR were in the other order, since it took only  
> one list.
>

LISP 1.5? Just how old ARE you? :)

-- 
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
From: jayessay
Subject: Re: how to define a local function
Date: 
Message-ID: <m3odlmga8s.fsf@sirius.goldenthreadtech.com>
Pascal Bourguignon <···@informatimago.com> writes:

> jayessay <······@foo.com> writes:
> > Does anyone remember the historical (or other) reason for why _labels_
> > is called "labels"?  It always seemed that the most likely name would
> > have been flet* (the above usage is particularly indicative of this in
> > comparison with let and let*).  Just curious, as I've never seen this
> > "explained"...
> 
> In LISP 1.5, there was a LABEL operator to make self-recursive lambdas.
> 
> Here is the meta-source of APPLY in LISP 1.5:
> 
>        REM APPLY(F,L,A) =
>        REM    SELECT(CAR(L).,
>        REM           -1,APP2(F,L,A).,
>        REM           LAMBDA,EVAL(F,APPEND(PAIR(CADR(F),L),A)).,
>        REM           LABEL,APPLY(CADDR(F),L,APPEND(
>        REM                PAIR1(CADR(F),CADDR(F))),A).,
>        REM           APPLY(EVAL(F,A),L,A))

Thanks.  That seems to provide some historical context for an early
appearance of it.  Presumably(??) this mutated into the labels of
MacLisp which then found its way into CL.  I guess the thing then is
why the operator in 1.5 was called "labels" (maybe I'm just dense, but
I can't see the connection in this context either...).  This is just
etymology - not important, just casually interesting.


/Jon

-- 
'j' - a n t h o n y at romeo/charley/november com
From: Pascal Bourguignon
Subject: Re: how to define a local function
Date: 
Message-ID: <87irbsfwzc.fsf@voyager.informatimago.com>
jayessay <······@foo.com> writes:

> Pascal Bourguignon <···@informatimago.com> writes:
>
>> jayessay <······@foo.com> writes:
>> > Does anyone remember the historical (or other) reason for why _labels_
>> > is called "labels"?  It always seemed that the most likely name would
>> > have been flet* (the above usage is particularly indicative of this in
>> > comparison with let and let*).  Just curious, as I've never seen this
>> > "explained"...
>> 
>> In LISP 1.5, there was a LABEL operator to make self-recursive lambdas.
>> 
>> Here is the meta-source of APPLY in LISP 1.5:
>> 
>>        REM APPLY(F,L,A) =
>>        REM    SELECT(CAR(L).,
>>        REM           -1,APP2(F,L,A).,
>>        REM           LAMBDA,EVAL(F,APPEND(PAIR(CADR(F),L),A)).,
>>        REM           LABEL,APPLY(CADDR(F),L,APPEND(
>>        REM                PAIR1(CADR(F),CADDR(F))),A).,
>>        REM           APPLY(EVAL(F,A),L,A))
>
> Thanks.  That seems to provide some historical context for an early
> appearance of it.  Presumably(??) this mutated into the labels of
> MacLisp which then found its way into CL.  I guess the thing then is
> why the operator in 1.5 was called "labels" (maybe I'm just dense, but
> I can't see the connection in this context either...).  This is just
> etymology - not important, just casually interesting.

Because it attached a 'label' to the recursive function for it to call
itself.

It could have been called NAME or TAG, etc, but label was often used
in assembler for the names of the instrutions.

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
You never feed me.
Perhaps I'll sleep on your face.
That will sure show you.
From: Matthias Benkard
Subject: Re: how to define a local function
Date: 
Message-ID: <1176332483.212097.190550@y80g2000hsf.googlegroups.com>
Hi,

> Maybe I'm missing something, but is there a reason to not just always
> use labels?  In a non-recursive definition, what does flet buy you
> over labels?

http://www-jcsu.jesus.cam.ac.uk/~csr21/lispfaq.html#AEN240

Good night,
Matthias