From: Tonci Damjanic
Subject: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fljf3zib0z7o$.7cs4xzopjub$.dlg@40tude.net>
Hi!

I have a new problem, regarding evaluation of S-expressions. I'm writing in
Common Lisp, CLISP implementation.

I cannot evaluate a form as a lambda expression if it has symbols other
than "usual" mathematical functions, i.e. this code breaks:

(setf my-expr '(+ 1 x))
(eval (funcall #'(lambda (x) my-expr) <some_value>))

But, if I alter my-expr into this:

(setf my-expr '(+ 1 2))

the call to EVAL returns 3 as expected. I cannot embed my-expr in the code,
because my-expr is build dynamically, during runtime.

I believe that the solution is simple, but I don't see it. I've tried using
APPLY and COERCE, but it seems to me that they're designed for different
usage...

Thanks!
Tonci
-- 
"For millions of years mankind lived just like the animals
Then something happened which unleashed the power of our imagination
We learned to talk"

From: Thomas A. Russ
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <ymi3auni0qc.fsf@blackcat.isi.edu>
Tonci Damjanic <··············@st.t-com.hr> writes:

> Hi!
> 
> I have a new problem, regarding evaluation of S-expressions. I'm writing in
> Common Lisp, CLISP implementation.
> 
> I cannot evaluate a form as a lambda expression if it has symbols other
> than "usual" mathematical functions, i.e. this code breaks:
> 
> (setf my-expr '(+ 1 x))
> (eval (funcall #'(lambda (x) my-expr) <some_value>))
> 
> But, if I alter my-expr into this:
> 
> (setf my-expr '(+ 1 2))
> 
> the call to EVAL returns 3 as expected. I cannot embed my-expr in the code,
> because my-expr is build dynamically, during runtime.

Others have pointed out the problem and some solutions.  I will note
that one way to debug things like this (and malfunctioning lisp code in
general) is to take advantage of the interactive environment and start
seeing what bits and pieces start doing.

So, for example, if (eval (funcall ...)) doesn't do what you want, you
should start examining the values returned by the argument forms.  In
this case, you would want to see what

  (funcall #'(lambda (x) my-expr) 2)

returns.  That's when you discover that this returns

  (+ 1 x)

and not, perhaps the (+ 1 2) that you expected.  It is also why setting
the value of MY-EXPR to (+ 1 2) does do what you want.  MY-EXPR is only
evaluated once, and that is when the (lambda (x) my-expr) is funcalled.
The lambda expression returns the value of MY-EXPR, but it isn't
affected by the binding of X, because the value of MY-EXPR is a
constant.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Maciej Katafiasz
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fiq8ct$vl0$1@news.net.uni-c.dk>
Den Sat, 01 Dec 2007 00:31:05 +0100 skrev Tonci Damjanic:

> I cannot evaluate a form as a lambda expression if it has symbols other
> than "usual" mathematical functions, i.e. this code breaks:
> 
> (setf my-expr '(+ 1 x))
> (eval (funcall #'(lambda (x) my-expr) <some_value>))
> 
> But, if I alter my-expr into this:
> 
> (setf my-expr '(+ 1 2))
> 
> the call to EVAL returns 3 as expected. I cannot embed my-expr in the
> code, because my-expr is build dynamically, during runtime.
> 
> I believe that the solution is simple, but I don't see it. I've tried
> using APPLY and COERCE, but it seems to me that they're designed for
> different usage...

CL-USER> (eval `(funcall #'(lambda (x) ,my-expr) 2))
3

You need to supply _forms_ to EVAL, and in your code you were supplying 
the _result_ of evaluating them outside of EVAL.

Cheers,
Maciej
From: Tonci Damjanic
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <1eznqs89osiss$.1m2jw0npunieb$.dlg@40tude.net>
On Sat, 1 Dec 2007 00:03:41 +0000 (UTC), Maciej Katafiasz wrote:

>> I believe that the solution is simple, but I don't see it. I've tried
>> using APPLY and COERCE, but it seems to me that they're designed for
>> different usage...
> 
> CL-USER> (eval `(funcall #'(lambda (x) ,my-expr) 2))
> 3
> 
> You need to supply _forms_ to EVAL, and in your code you were supplying 
> the _result_ of evaluating them outside of EVAL.

I said that it was simple! :)

Thanks again!

Tonci
-- 
"For millions of years mankind lived just like the animals
Then something happened which unleashed the power of our imagination
We learned to talk"
From: Andreas Thiele
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fiq8m1$9fe$03$1@news.t-online.com>
"Tonci Damjanic" <··············@st.t-com.hr> schrieb im Newsbeitrag ···································@40tude.net...
> Hi!
>
> I have a new problem, regarding evaluation of S-expressions. I'm writing in
> Common Lisp, CLISP implementation.
>
> I cannot evaluate a form as a lambda expression if it has symbols other
> than "usual" mathematical functions, i.e. this code breaks:
>
> (setf my-expr '(+ 1 x))
> (eval (funcall #'(lambda (x) my-expr) <some_value>))
>
> But, if I alter my-expr into this:
>
> (setf my-expr '(+ 1 2))
>
> the call to EVAL returns 3 as expected. I cannot embed my-expr in the code,
> because my-expr is build dynamically, during runtime.
>
> I believe that the solution is simple, but I don't see it. I've tried using
> APPLY and COERCE, but it seems to me that they're designed for different
> usage...
>
> Thanks!
> Tonci
> -- 
> "For millions of years mankind lived just like the animals
> Then something happened which unleashed the power of our imagination
> We learned to talk"

Hi Tonci,

eval executes within a null/nil lexical environment, thus you have no access to your lambda's x.

You can do the following

CL-USER 29 > (setf my-expr '(+ 1 x))
(+ 1 X)

CL-USER 30 > (setf fn (eval (list 'lambda '(x) my-expr)))
#<anonymous interpreted function 200DC482>

CL-USER 31 > (funcall fn 4)
5

Sorry, I'm just a hacker, not a teacher :)

Andreas

P.S. You might be interested in: www.flownet.com/gat/specials.pdf
From: Andreas Thiele
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fiq9k0$o72$01$1@news.t-online.com>
"Tonci Damjanic" <··············@st.t-com.hr> schrieb im Newsbeitrag ···································@40tude.net...
> Hi!
>
> I have a new problem, regarding evaluation of S-expressions. I'm writing in
> Common Lisp, CLISP implementation.
>
> I cannot evaluate a form as a lambda expression if it has symbols other
> than "usual" mathematical functions, i.e. this code breaks:
>
> (setf my-expr '(+ 1 x))
> (eval (funcall #'(lambda (x) my-expr) <some_value>))
>
> But, if I alter my-expr into this:
>
> (setf my-expr '(+ 1 2))
>
> the call to EVAL returns 3 as expected. I cannot embed my-expr in the code,
> because my-expr is build dynamically, during runtime.
>
> I believe that the solution is simple, but I don't see it. I've tried using
> APPLY and COERCE, but it seems to me that they're designed for different
> usage...
>
> Thanks!
> Tonci
> -- 
> "For millions of years mankind lived just like the animals
> Then something happened which unleashed the power of our imagination
> We learned to talk"

Tonci,

I think you are not aware, what your lambda returns. You lambda returns my-expr, that is
'(+ 1 x) this gets evalutated _after_ your funcall, when your parameter already is in nirwana :)
Thus your constant example works. So basically the idea is, generate the code for the lambda
and evaluate this code. So you obtain a lambda which can be funcalled (s. my last post).

eval has no lexical environment, you don't have access to lexical scoped variables, but the
lambda establishes an environment for the code when funcalled. A bit tricky, but once
understood utterly powerful.

Andreas
From: Tonci Damjanic
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <jtbh4080kfgo.5akt4gs0c2u5.dlg@40tude.net>
On Sat, 1 Dec 2007 01:24:30 +0100, Andreas Thiele wrote:

> I think you are not aware, what your lambda returns. You lambda returns my-expr, that is
> '(+ 1 x) this gets evalutated _after_ your funcall, when your parameter already is in nirwana :)
> Thus your constant example works. So basically the idea is, generate the code for the lambda
> and evaluate this code. So you obtain a lambda which can be funcalled (s. my last post).

Alright, I understand the procedure now. These obscure behaviour confused
me, but now I think it's clearing in my head. Maciej gave me good and
simple solution which works just fine...

> eval has no lexical environment, you don't have access to lexical scoped variables, but the
> lambda establishes an environment for the code when funcalled. A bit tricky, but once
> understood utterly powerful.

Yeah, I realize this now. :)
Well, thanks for the thorough explanation...

Tonci
-- 
"For millions of years mankind lived just like the animals
Then something happened which unleashed the power of our imagination
We learned to talk"
From: Andreas Thiele
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fiqbts$s5d$01$1@news.t-online.com>
"Tonci Damjanic" <··············@st.t-com.hr> schrieb im Newsbeitrag ··································@40tude.net...
> On Sat, 1 Dec 2007 01:24:30 +0100, Andreas Thiele wrote:
>
>> I think you are not aware, what your lambda returns. You lambda returns my-expr, that is
>> '(+ 1 x) this gets evalutated _after_ your funcall, when your parameter already is in nirwana :)
>> Thus your constant example works. So basically the idea is, generate the code for the lambda
>> and evaluate this code. So you obtain a lambda which can be funcalled (s. my last post).
>
> Alright, I understand the procedure now. These obscure behaviour confused
> me, but now I think it's clearing in my head. Maciej gave me good and
> simple solution which works just fine...
>
>> eval has no lexical environment, you don't have access to lexical scoped variables, but the
>> lambda establishes an environment for the code when funcalled. A bit tricky, but once
>> understood utterly powerful.
>
> Yeah, I realize this now. :)
> Well, thanks for the thorough explanation...
>
> Tonci
> -- 
> "For millions of years mankind lived just like the animals
> Then something happened which unleashed the power of our imagination
> We learned to talk"

Another hint: in case you need more performance, you can compile the lambda.
With

(setf fn (compile nil fn))

all further funcalls on fn will use the compiled version.


BTW Maciej's version is equivalent to mine

(list 'lambda '(x) my-expr)

can be abbreviated using back-quote syntax as

`(lambda (x) ,my-expr)


Happy hacking

Andreas 
From: Tonci Damjanic
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <s2yp1pt8cltx.164unhdlo78c3.dlg@40tude.net>
On Sat, 1 Dec 2007 02:03:54 +0100, Andreas Thiele wrote:

> Another hint: in case you need more performance, you can compile the lambda.
> With
> 
> (setf fn (compile nil fn))
> 
> all further funcalls on fn will use the compiled version.

Yes, I know about this possibility, but as I'm programming a genetic
algorithm solver, the mentioned function mutates all the time so
compilation maybe wouldn't speed things up...

> BTW Maciej's version is equivalent to mine
> 
> (list 'lambda '(x) my-expr)
> 
> can be abbreviated using back-quote syntax as
> 
> `(lambda (x) ,my-expr)

Yes, of course it is. He was the first one to answer my original post and
that's why I mentioned him. No extra reasons...

Tonci
-- 
"For millions of years mankind lived just like the animals
Then something happened which unleashed the power of our imagination
We learned to talk"
From: Andreas Thiele
Subject: Re: Evaluating S-expresssions with symbols
Date: 
Message-ID: <fiqd2u$u47$01$1@news.t-online.com>
"Tonci Damjanic" <··············@st.t-com.hr> schrieb im Newsbeitrag ···································@40tude.net...
> On Sat, 1 Dec 2007 02:03:54 +0100, Andreas Thiele wrote:
>
>> Another hint: in case you need more performance, you can compile the lambda.
>> With
>>
>> (setf fn (compile nil fn))
>>
>> all further funcalls on fn will use the compiled version.
>
> Yes, I know about this possibility, but as I'm programming a genetic
> algorithm solver, the mentioned function mutates all the time so
> compilation maybe wouldn't speed things up...
>
>> BTW Maciej's version is equivalent to mine
>>
>> (list 'lambda '(x) my-expr)
>>
>> can be abbreviated using back-quote syntax as
>>
>> `(lambda (x) ,my-expr)
>
> Yes, of course it is. He was the first one to answer my original post and
> that's why I mentioned him. No extra reasons...
>
> Tonci
> -- 
> "For millions of years mankind lived just like the animals
> Then something happened which unleashed the power of our imagination
> We learned to talk"

OK, I guess I'm teaching too much :))

Andreas