From: Ryan C. Tarpine
Subject: Macros in the car of an application
Date: 
Message-ID: <Pine.LNX.4.58-035.0403031405230.3046@unix44.andrew.cmu.edu>
After seeing some Scheme code where lambdas took other functions as
arguments and called them easily (e.g. (lambda (f) (f 3))), I thought I'd
try to write a macro that would allow things like that.  My result was
a macro I called flambda.  It's like lambda but you put an extra quote
around arguments intended to be functions, and these variables are put
into an flet.  For example:

(flambda ('f 'g x) (f (g x)))
       |
       V
#'(lambda (f g x)
    (flet ((f (&rest args) (apply f args))
           (g (&rest args) (apply g args)))
      (f (g x))))

This works fine if I use it like this:
> (flambda ('f 'g x) (f (g x)))
#<Anonymous blah blah>
> (funcall * #'/ #'1+ 23)
1/24

But when I try to use it in place,
> ((flambda ('f 'g x) (f (g x))) #'/ #'1+ 23)
Error: Car of ((flambda etc) etc) is not a function name of
lambda-expression.

Why isn't it being expanded into the lambda expression it should be?

Thanks,
Ryan

--
A witty saying proves nothing, but saying something pointless gets
people's attention.

From: Kaz Kylheku
Subject: Re: Macros in the car of an application
Date: 
Message-ID: <cf333042.0403031619.42d5afe4@posting.google.com>
"Ryan C. Tarpine" <········@andrew.cmu.edu> wrote in message news:<····································@unix44.andrew.cmu.edu>...
> After seeing some Scheme code where lambdas took other functions as
> arguments and called them easily (e.g. (lambda (f) (f 3))), I thought I'd
> try to write a macro that would allow things like that.  My result was
> a macro I called flambda.  It's like lambda but you put an extra quote
> around arguments intended to be functions, and these variables are put
> into an flet.  For example:
> 
> (flambda ('f 'g x) (f (g x)))
>        |
>        V
> #'(lambda (f g x)
>     (flet ((f (&rest args) (apply f args))
>            (g (&rest args) (apply g args)))
>       (f (g x))))

Note that your macro could assume that all of the lambda variables are
potentially functions, and set up FLET-s for all of them. There is no
harm in

  (x (&rest args) (apply x args))

the error that x does not refer to a function only occurs if the
user-supplied body actually tries to call x. In effect, what you are
doing is eradicating the separation of namespaces for the designated
symbols by duplicating the value bindings into function bindings.

I'd do this by writing a lower-level FVLET macro that does the
rebinding. The flambda could then just be implemented on top of that
as (lambda (f g ...) (fvlet(f g ...) ... body).

> This works fine if I use it like this:
> > (flambda ('f 'g x) (f (g x)))
>  #<Anonymous blah blah>
> > (funcall * #'/ #'1+ 23)
> 1/24
> 
> But when I try to use it in place,
> > ((flambda ('f 'g x) (f (g x))) #'/ #'1+ 23)
> Error: Car of ((flambda etc) etc) is not a function name of
> lambda-expression.
>
> Why isn't it being expanded into the lambda expression it should be?

Because the first position of a list form is not evaluated in the same
way as the other positions. It is subject to special rules: it must
contain a function name or lambda expression. A ``flambda expression''
is not either of these, and so it doesn't work.

Macro-expansion is not carried out, so you cannot even have a macro
call that expands to one of the allowed forms.

Creating function bindings out of value bindings only does half the
job of eradicating the dual namespace. You have run into the other
half: the special evaluation rules.

About all you can do is use nesting.

  (fvlet ((fl (flambda (x y ...) ...))
          f g h)
     (fl f g h))

Here (fl ...) is okay, because the macro set up FL as a function name
via FLET, and also set up a value binding FL.

Your job is to write FVLET and then rewrite FLAMBDA in terms of that.

FVLET sets up a flet for all of the specified symbols, and for the
forms that are (<symbol> <expr>), it arranges for the evaluation of
<expr> whose value is used to set up a FLET, as well as a value
binding, so the expansion of the above is:

  (let ((fl (flambda ...)))
    (flet ((fl (args) (apply fl args))
           (f (args) ...)
           (g (args) ...)
           (h (args) ...))
     (f1 f g h)))

Expanding to two nested binding constructs is a bit lame, because of
breakage with respect to declarations.
From: Peter Seibel
Subject: Re: Macros in the car of an application
Date: 
Message-ID: <m3wu61iu4x.fsf@javamonkey.com>
"Ryan C. Tarpine" <········@andrew.cmu.edu> writes:

> After seeing some Scheme code where lambdas took other functions as
> arguments and called them easily (e.g. (lambda (f) (f 3))), I
> thought I'd try to write a macro that would allow things like that.
> My result was a macro I called flambda. It's like lambda but you put
> an extra quote around arguments intended to be functions, and these
> variables are put into an flet. For example:
>
> (flambda ('f 'g x) (f (g x)))
>        |
>        V
> #'(lambda (f g x)
>     (flet ((f (&rest args) (apply f args))
>            (g (&rest args) (apply g args)))
>       (f (g x))))
>
> This works fine if I use it like this:
>> (flambda ('f 'g x) (f (g x)))
> #<Anonymous blah blah>
>> (funcall * #'/ #'1+ 23)
> 1/24
>
> But when I try to use it in place,
>> ((flambda ('f 'g x) (f (g x))) #'/ #'1+ 23)
> Error: Car of ((flambda etc) etc) is not a function name of
> lambda-expression.
>
> Why isn't it being expanded into the lambda expression it should be?

For the same reason the name of a variable that happens to hold a
function can't be used in the first position (i.e. the very thing
you're trying to work around). See 3.1.2.1.2 Conses as Forms in the
hyperspec or meditate a bit more on the true difference between a
Lisp-1 (such as Scheme) and a Lisp-2 (such as Common Lisp).

Or google for the many, many past threads in this group on the topic
of Lisp-1 vs Lisp-2.

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

         Lisp is the red pill. -- John Fraser, comp.lang.lisp
From: Kristian Elof Sørensen
Subject: Re: Macros in the car of an application
Date: 
Message-ID: <40465277$0$170$edfadb0f@dread11.news.tele.dk>
Hi

Ryan C. Tarpine wrote:
> After seeing some Scheme code where lambdas took other functions as
> arguments and called them easily (e.g. (lambda (f) (f 3))), I thought I'd
> try to write a macro that would allow things like that.  My result was
> a macro I called flambda.  It's like lambda but you put an extra quote
> around arguments intended to be functions, and these variables are put
> into an flet.  For example:

Have a look at:
"Technical Issues of Separation in Function Cells and Value Cells"
by Richard P. Gabriel and Kent M. Pitman

http://www.dreamsongs.com/Separation.html

It explains both why and how Common Lisp and Schema differes with regard 
to when identifiers are evaluated for the function and when they are 
evaluated for the value.

The authors are two of the authors of the ANSI standard for Common Lisp, 
so you will be hard pressed to find a more authoritative source of 
information on this topic ;-)


-- 
-----------------------    http://www.elof.dk    ----------------------
Kristian Elof Soerensen   elof at image dot dk        (+45) 45 93 92 02
From: Pascal Costanza
Subject: Re: Macros in the car of an application
Date: 
Message-ID: <c25m7n$87o$1@newsreader2.netcologne.de>
Kristian Elof S�rensen wrote:

> Hi
> 
> Ryan C. Tarpine wrote:
> 
>> After seeing some Scheme code where lambdas took other functions as
>> arguments and called them easily (e.g. (lambda (f) (f 3))), I thought I'd
>> try to write a macro that would allow things like that.  My result was
>> a macro I called flambda.  It's like lambda but you put an extra quote
>> around arguments intended to be functions, and these variables are put
>> into an flet.  For example:
> 
> Have a look at:
> "Technical Issues of Separation in Function Cells and Value Cells"
> by Richard P. Gabriel and Kent M. Pitman
> 
> http://www.dreamsongs.com/Separation.html

This is indeed an excellent paper, but you might also want to take a 
look at 
http://groups.google.com/groups?selm=costanza-DA096C.23503006062003%40news.netcologne.de 
where I presented one possible resolution of the Lisp-1 vs. Lisp-2 debate.

Erann Gat's paper about locales presents another solution. See 
http://www.flownet.com/gat/locales.pdf [1]



Pascal

[1] I find his criticism of packages in that paper a little unfortunate. 
That's mainly because I think that packages are extremely cool. But 
that's a different story, in fact unrelated to the Lisp-1/2 issue.

-- 
1st European Lisp and Scheme Workshop
June 13 - Oslo, Norway - co-located with ECOOP 2004
http://www.cs.uni-bonn.de/~costanza/lisp-ecoop/