From: Mattias Nilsson
Subject: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <1138836711.025391.231520@g47g2000cwa.googlegroups.com>
OK, so this is another possibly silly question, but I don't mind
feeling silly on my way to enlightenment.

Going from code to data in CL is easy; just quote the code.
But how do you go the other way, without using
the-often-warned-about EVAL?

After having done (defparameter *form* '(+ 1 2)), how do you
evaluate the value of *form* without giving in to temptation and
just go with (eval *form*)?

My example is extremely unusable, and I _don't_ know why I
would want to do such a thing, but I _do_ want to know if it's
possible, and if so, how?

Best Regards,
Mattias Nilsson.

From: Wade Humeniuk
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <hHbEf.175069$km.35517@edtnps89>
Mattias Nilsson wrote:
> OK, so this is another possibly silly question, but I don't mind
> feeling silly on my way to enlightenment.
> 
> Going from code to data in CL is easy; just quote the code.
> But how do you go the other way, without using
> the-often-warned-about EVAL?
> 
> After having done (defparameter *form* '(+ 1 2)), how do you
> evaluate the value of *form* without giving in to temptation and
> just go with (eval *form*)?
> 
> My example is extremely unusable, and I _don't_ know why I
> would want to do such a thing, but I _do_ want to know if it's
> possible, and if so, how?
> 

CL-USER 1 > (defparameter *form* '(+ 1 2))
*FORM*

CL-USER 2 > (apply (car *form*) (cdr *form*))
3

CL-USER 3 >

Wade
From: Mattias Nilsson
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <1138837954.831701.21660@z14g2000cwz.googlegroups.com>
> CL-USER 1 > (defparameter *form* '(+ 1 2))
> *FORM*
>
> CL-USER 2 > (apply (car *form*) (cdr *form*))
> 3

I knew I made my example too simple... What about '(* 2 (* 2 (* 2 2))),
and so on? Is recursion the only way to go?

Mattias.
From: Barry Margolin
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <barmar-9133EA.23453301022006@comcast.dca.giganews.com>
In article <·······················@z14g2000cwz.googlegroups.com>,
 "Mattias Nilsson" <········@bredband.net> wrote:

> > CL-USER 1 > (defparameter *form* '(+ 1 2))
> > *FORM*
> >
> > CL-USER 2 > (apply (car *form*) (cdr *form*))
> > 3
> 
> I knew I made my example too simple... What about '(* 2 (* 2 (* 2 2))),
> and so on? Is recursion the only way to go?

Google for "metacircular evaluator".

-- 
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: Wade Humeniuk
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <GpcEf.175335$km.33396@edtnps89>
Mattias Nilsson wrote:
>> CL-USER 1 > (defparameter *form* '(+ 1 2))
>> *FORM*
>>
>> CL-USER 2 > (apply (car *form*) (cdr *form*))
>> 3
> 
> I knew I made my example too simple... What about '(* 2 (* 2 (* 2 2))),
> and so on? Is recursion the only way to go?
> 


Maybe... (as we get embark on the way to implementing eval)

(defun my-eval (form)
   (apply (car form) (mapcar 'form-value (cdr form))))

(defun form-value (form)
   (typecase form
     (keyword form)
     (symbol (symbol-value form))
     (null nil)
     (list (if (eql 'quote (car form))
               (cadr form)
             (my-eval form)))
     (t form)))

CL-USER 1 > (my-eval '(* 2 (* 2 (* 2 2))))
16

CL-USER 2 > (defvar x 10)
X

CL-USER 3 > (my-eval '(* 2 (* 2 (* x x))))
400


Wade
From: Pascal Costanza
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <44cvs3F1duniU1@individual.net>
Mattias Nilsson wrote:
> OK, so this is another possibly silly question, but I don't mind
> feeling silly on my way to enlightenment.
> 
> Going from code to data in CL is easy; just quote the code.
> But how do you go the other way, without using
> the-often-warned-about EVAL?
> 
> After having done (defparameter *form* '(+ 1 2)), how do you
> evaluate the value of *form* without giving in to temptation and
> just go with (eval *form*)?
> 
> My example is extremely unusable, and I _don't_ know why I
> would want to do such a thing, but I _do_ want to know if it's
> possible, and if so, how?

In most cases, you can create closures:

(defparameter *closure* (lambda () (+ 1 2)))

(funcall *closure*)

By using higher-order functions, you can create new code at runtime out 
of existing building blocks:

(defun adder (x)
   (lambda (y) (+ x y)))

(funcall (adder 5) 10)

Using closures like this is typically preferable because:
- Closures can be compiled upfront, so you will get efficient code.
- They can capture the lexical environment: In the adder example, the 
generated closure sees the correct binding of x that is passed to the 
adder function.

Using eval in conjunction with s-expressions is typically a bad idea 
because here it is exactly the other way around:
- S-expressions cannot be compiled upfront. The code has to be 
interpreted or compiled at runtime which is much more time consuming.
- Code executed by eval cannot capture the lexical enviroment. They can 
only see global definititons and dynamically scoped variables.

Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/
From: Mattias Nilsson
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <1138840020.911777.173000@o13g2000cwo.googlegroups.com>
Pascal Costanza wrote:

> Using closures like this is typically preferable because:
> - Closures can be compiled upfront, so you will get efficient code.
> - They can capture the lexical environment: In the adder example, the
> generated closure sees the correct binding of x that is passed to the
> adder function.
>
> Using eval in conjunction with s-expressions is typically a bad idea
> because here it is exactly the other way around:
> - S-expressions cannot be compiled upfront. The code has to be
> interpreted or compiled at runtime which is much more time consuming.
> - Code executed by eval cannot capture the lexical enviroment. They can
> only see global definititons and dynamically scoped variables.

I guess the idea I was toying with that lead to my original question
involved code that:
- Should be compiled upfront.
- Would refuse to capture the lexical environment.

But I guess closures and a bit of discipline would do just fine.
Thanks, Pascal!

Mattias.
From: Pascal Bourguignon
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <878xsue83m.fsf@thalassa.informatimago.com>
"Mattias Nilsson" <········@bredband.net> writes:

> Pascal Costanza wrote:
>
>> Using closures like this is typically preferable because:
>> - Closures can be compiled upfront, so you will get efficient code.
>> - They can capture the lexical environment: In the adder example, the
>> generated closure sees the correct binding of x that is passed to the
>> adder function.
>>
>> Using eval in conjunction with s-expressions is typically a bad idea
>> because here it is exactly the other way around:
>> - S-expressions cannot be compiled upfront. The code has to be
>> interpreted or compiled at runtime which is much more time consuming.
>> - Code executed by eval cannot capture the lexical enviroment. They can
>> only see global definititons and dynamically scoped variables.
>
> I guess the idea I was toying with that lead to my original question
> involved code that:
> - Should be compiled upfront.
> - Would refuse to capture the lexical environment.
>
> But I guess closures and a bit of discipline would do just fine.
> Thanks, Pascal!

Pascal gives good advice.  I'd add that there are several other ways
to go from "data" to "code":  

- you can write an interpreter.  This allows you to do this data->code
  transitions with total security: the user cannot break your program
  or your system.  

  (Of course, if you're on the way of Greenspun City, you may be
  better to use EVAL anyways.) 


- you can just compile a new function:

  (let ((sexp '(+ (* a x x) (* b x) c))
        (args '(a b c))
        (var 'x))
   (let ((source (list 'lambda args (list 'lambda (list var) sexp))))
    (print source)
    (let ((user-function (compile nil source)))
        (print (funcall (funcall user-function 2 4 -2) 3)))))
 
  But as with EVAL, you don't capture the lexical state of your
  program, of course.  For this you need closures.



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

NEW GRAND UNIFIED THEORY DISCLAIMER: The manufacturer may
technically be entitled to claim that this product is
ten-dimensional. However, the consumer is reminded that this
confers no legal rights above and beyond those applicable to
three-dimensional objects, since the seven new dimensions are
"rolled up" into such a small "area" that they cannot be
detected.
From: Thomas F. Burdick
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <xcvpsm653nf.fsf@conquest.OCF.Berkeley.EDU>
"Mattias Nilsson" <········@bredband.net> writes:

> OK, so this is another possibly silly question, but I don't mind
> feeling silly on my way to enlightenment.
> 
> Going from code to data in CL is easy; just quote the code.
> But how do you go the other way, without using
> the-often-warned-about EVAL?

EVAL is exactly the right tool for the job of going from data to code.
However...

> My example is extremely unusable, and I _don't_ know why I
> would want to do such a thing, but I _do_ want to know if it's
> possible, and if so, how?

... the reason you're warned about EVAL is not because it doesn't do
its job perfectly well.  You're warned about EVAL because there's
usually a better way to solve something than interpreting
s-expressions as code at runtime.  Usually by throwing closures at the
problem.

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | Free Mumia Abu-Jamal! |
     ,--'    _,'   | Abolish the racist    |
    /       /      | death penalty!        |
   (   -.  |       `-----------------------'
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Thomas A. Russ
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <ymiu0bhoer7.fsf@sevak.isi.edu>
"Mattias Nilsson" <········@bredband.net> writes:

What the others said.

> Going from code to data in CL is easy; just quote the code.
> But how do you go the other way, without using
> the-often-warned-about EVAL?

EVAL is actually present in the language for a reason.  Evaluating
arbitrary code is what it is supposed to do, so if you are, in fact,
writing an evaluator for some language, then EVAL may be the appropriate
choice.

The reason for the warning is that very often new lisp users become so
enamored of the function that it gets overused, an in particular, leads
to the construction of code that is then immediately EVALed, instead of
using some other, more appropriate construct.

For a completely contrived example, consider:

(defun set-global (symbol value)
  (eval `(setq ,symbol ,value)))

instead of finding and using
   (set symbol value)

-Tom.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Mattias Nilsson
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <1138921099.070644.232640@g43g2000cwa.googlegroups.com>
Thomas A. Russ wrote:

> The reason for the warning is that very often new lisp users become so
> enamored of the function that it gets overused, an in particular, leads
> to the construction of code that is then immediately EVALed, instead of
> using some other, more appropriate construct.

Thank you all for your answers and comments. Just one more example:

Let's say I want to write a (simple) tutorial on CL for the complete
beginner, in CL itself, showing the basic evaluation of forms. I create
a list of quoted code:
'('symbol :keyword (quote symbol) (- 3 2 1))
and want to demonstrate the evaluation of these forms by printing the
forms and their values, as well as some explanation of what is going
on. Would EVAL be appropriate in such a case?

Mattias
From: ··············@hotmail.com
Subject: Re: Newbie: Evaluation without EVAL ?
Date: 
Message-ID: <1138928029.116984.321320@o13g2000cwo.googlegroups.com>
Mattias Nilsson wrote:
> Let's say I want to write a (simple) tutorial on CL for the complete
> beginner, in CL itself, showing the basic evaluation of forms. I create
> a list of quoted code:
> '('symbol :keyword (quote symbol) (- 3 2 1))
> and want to demonstrate the evaluation of these forms by printing the
> forms and their values, as well as some explanation of what is going
> on. Would EVAL be appropriate in such a case?

Your description is not crystal clear to me.

Are you trying to build some application that is a "visible" Common
Lisp implementation, where students type in expressions (as to the
interactive prompt of a usual CL implementation), but your application
explicitly and demonstratively breaks up the steps of the evaluation of
the expression, in order to demonstrate CL evaluation rules?

E.g. student types in (mapcar #'foo (list 1 2 3))  -->

"reading string (mapcar #'foo (list 1 2 3))"
"evaluating expression (CL:MAPCAR (CL:FUNCTION CL-USER:FOO) (CL:LIST 1
2 3))"
"CL:MAPCAR is fbound to #<function CL:MAPCAR>"
"evaluating argument (CL:FUNCTION CL-USER:FOO)" --> #<function FOO>"
"evaluating argument (CL:LIST 1 2 3) "
  ....
"calling #<function CL:MAPCAR>"
(foo-of-1 foo-of-2 foo-of-3) 

?