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