From: Pascal Bourguignon
Subject: Re: nested lambda-expressions
Date: 
Message-ID: <87oe85legc.fsf@thalassa.informatimago.com>
···@zedat.fu-berlin.de (Stefan Ram) writes:

>   I just wanted to try something with CLisp. Here is an
>   abbreviated transscript:
>
>> (setq inc (lambda (x)(+ 1 x)))
> #<FUNCTION :LAMBDA (X) (+ 1 X)>
>
>> (funcall inc 10)
> 11
>
>> (setq double (lambda (f)(lambda(x)(funcall f(funcall f x)))))
> #<FUNCTION :LAMBDA (F) (LAMBDA (X) (FUNCALL F (FUNCALL F X)))>
>
>   I.e., apply the function "f" twice, which is assumed
>   to be a function with one parameter.
>
>> (funcall double inc)
> #<FUNCTION :LAMBDA (X) (FUNCALL F (FUNCALL F X))>
>
>   I assume the last line to be the value of the expression
>   I have entered. How can "F" be a seemingly free variable
>   in the result and why is "inc" not used? 
>
>   I was actually trying to get something like:
>
> #<FUNCTION :LAMBDA (X) (FUNCALL INC (FUNCALL INC X))>
>
>   or even:
>
> #<FUNCTION :LAMBDA (X)(FUNCALL #<FUNCTION :LAMBDA (X) 
>       (+ 1 (FUNCALL #<FUNCTION :LAMBDA (X1) (+1 X1)>))>)>
>
>   Because I was curious to see how Lisp might rename the 
>   inner parameter "x".

Note that in clisp, until you compile the function, you can use
FUNCTION-LAMBDA-EXPRESSION to get the source and the environment:

[77]> (function-lambda-expression (funcall double inc))
(LAMBDA (X) (FUNCALL F (FUNCALL F X))) ;
#(#(F #<FUNCTION :LAMBDA (X) (+ 1 X)> NIL) NIL NIL NIL
  ((DECLARATION XLIB::ARRAY-REGISTER XLIB::INDENTATION XLIB::ARGLIST
    XLIB::CLX-VALUES OPTIMIZE DECLARATION))) ;
:LAMBDA

Here you see that f is bound to the inc function.

But don't count too much on FUNCTION-LAMBDA-EXPRESSION,
implementations are allowed to return NIL always.



Be assured however that you will always have:
    (= (+ x 2) (funcall (funcall double inc) x))


[78]> (dotimes (x 100) (assert (= (+ x 2) (funcall (funcall double inc) x))))
NIL


-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

This is a signature virus.  Add me to your signature and help me to live
From: Pascal Bourguignon
Subject: Re: nested lambda-expressions
Date: 
Message-ID: <87fythl9oa.fsf@thalassa.informatimago.com>
···@zedat.fu-berlin.de (Stefan Ram) writes:

> Pascal Bourguignon <····@mouse-potato.com> writes:
>>[77]> (function-lambda-expression (funcall double inc))
>
>   I see. In the meantime, I also tried this:
>
>>(setq double (lambda(f)(list 'lambda(list 'x)(list 'funcall f( list 'funcall f 'x)))))
> #<FUNCTION :LAMBDA (F)
>   (LIST 'LAMBDA (LIST 'X) (LIST 'FUNCALL F (LIST 'FUNCALL F 'X)))>
>
>> (funcall double inc)
> (LAMBDA (X)
>  (FUNCALL #<FUNCTION :LAMBDA (X) (+ 1 X)>
>   (FUNCALL #<FUNCTION :LAMBDA (X) (+ 1 X)> X)))
>
>> (funcall (eval (funcall double inc)) 2)
> 4

This double is more like a macro: instead of returning a function, it
returns a S-expression.



Actually, in CL, we use often the name "function" for both functions
and closures.  Closures are function+data.  (Yes, it's the same as objects).

When you write:
(setq double (lambda (f)(lambda(x)(funcall f(funcall f x)))))
you get in double a closure with no data, so it looks very like a function.

But when you execute (funcall double inc)
you get a true closure, with a function: (lambda(x)(funcall f(funcall f x)))
and a data ( = inc ) bound to the free variable f.

(funcall double inc) prints the function, not the closure. so you only
get part of the story, and you don't see that f is bound to inc.

Happily, FUNCTION-LAMBDA-EXPRESSION is allowed to return the
environment in addition to the function, so you can see the whole
closure.




-- 
__Pascal Bourguignon__                     http://www.informatimago.com/
In deep sleep hear sound,
Cat vomit hairball somewhere.
Will find in morning.