From: Bob Kerns
Subject: Re: setqing equations
Date: 
Message-ID: <1991Oct24.014420.9673@crl.dec.com>
In article <············@early-bird.think.com>, ······@think.com (Barry Margolin) writes:
> In article <············@dalembert.cs.widener.edu> ····@cs.widener.edu (Sven Heinicke) writes:
> >Is there anyway to get something like this to work:
> >
> >> (setq equation '(mod a b))
> >(* mod a b)
> 
> Where did the "*" come from?
> 
> >> (let ((a 20)(b 7)) (eval equation))
> >6
> 
> Bind the variables dynamically:
> 
> (let ((a 20)
>       (b 7))
>   (declare (special a b))
>   (eval equation))

I bet there's a better answer if we knew what he was
trying to do.  I don't think I've written a call to
EVAL in 10 years, except as part of a READ-EVAL-PRINT
loop or similar situation.

Equations perhaps should really be functions, not
forms.

But I won't make any flat claims unless I know more of
what's going on.  There ARE valid uses for EVAL; it's
just very rare in most kinds of program, including
symbolic mathematics!

From: Bob Kerns
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Oct25.031245.12005@crl.dec.com>
In article <·····················@arris.com>, ········@arris.com (Richard Shapiro) writes:
> In article <·····················@crl.dec.com> ···@crl.dec.com (Bob Kerns) writes:
> >There ARE valid uses for EVAL; it's
> >just very rare in most kinds of program, including
> >symbolic mathematics!
> 
> Not really all that rare. Any application which needs to construct
> forms dynamically and then evaluate them requires EVAL. I would
> venture to say that most reasonably sophisticated, interactive
> programs need this capability. In fact, the fact that Lisp can do this
> is one of the better arguments for using Lisp rather than, say, C.

Generally this can be better done by having a function which
returns a closure.  The fact that you can do this is a far better
and far more important argument for using Lisp over C.  This
approach results in clearer code, less consing, far less paging,
and much faster code.

Note that it *IS* very common to use APPLY.  A lot of the things
beginners use EVAL for can be better written with APPLY.  For
example, it is common to build a list who's CAR is a function and
who's CDR is a list of argument values, and pass this around or
store it away.  Later, you'd apply the CAR to the CDR.

Some would instead do `(,fun ',arg1 ',arg2) and call EVAL, but
usually this technique is really just capturing a function and
arguments, and the use of APPLY makes this clearer by not suggesting
otherwise.

Actually, a better way of doing this might be to return a closure
of zero arguments, which applys the function to the arguments, and
just always call APPLY with no arguments.

Another common reason for using EVAL is confusion regarding
how to use macros.  Either the macros were written badly, or
should not have been macros, or had an inappropriate contract.

> I understand the pedagogic reasons for saying "Don't use EVAL". But
> this has frequently been transformed into "If you're using EVAL,
> you're probably wrong," which is not only untrue but really very bad
> pedagogy -- when the student does not need to use it, he or she will
> waste time and enery trying to figure out what's "wrong".

Well, statistically speaking, I would have to say that it IS
true.  The vast majority of uses of EVAL I have seen over the
years HAVE been wrong.  It's a little strongly stated, but in
both this statement and mine, the message is "If you're about
to use EVAL, you should rethink your problem first".  I think
this is good advice.

> The statement quoted above is better, but better still would be:
> 
>   There are valid uses for EVAL, but it's very rare in simple
>   applications. 

It is also very rare in complex applications.

It is so rare that I think it worthwhile to list a few exceptions.

* Read-Eval-Print loops.  (That is, tools for interactive use of
  the language).

* Lisp compilers' implementation of EVAL-WHEN.

* Lisp loaders.

* Macros pre-evaluating constant forms.  Actually, there's a
  semantic bug here; CONSTANTP should be taking an environment
  argument, and there should be a parallel EVAL-CONSTANT, but
  ANSI sort of blew it and didn't provide the right tools.  Watch
  out for DEFCONSTANT if you do this!

* Debugging tools.

Over the years I have converted a lot of code from using EVAL.
It generally makes the code much more clear, and often there
were semantic bugs in the original code as a result of the use
of EVAL.  Often a significant performance improvement resulted,
because instead of running the interpreter, the modified code
would run pieces of compiled code.

I have written a lot of code over the last years, much of it
involving complex systems, and the vast majority of it not
using EVAL at all.  (Contrary to my prior statement that all
of my uses of EVAL in the last decade were read/eval/print
loops, I have written each of the exceptions I list above, but
that's all I've been able to recall so far).
From: Barry Margolin
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <kgflpaINN8tm@early-bird.think.com>
In article <······················@crl.dec.com> ···@crl.dec.com (Bob Kerns) writes:
>It is so rare that I think it worthwhile to list a few exceptions.
>
>* Read-Eval-Print loops.  (That is, tools for interactive use of
>  the language).

This includes things like Emacs's M-escape command.

One other legitimate reason I've seen for using EVAL is to invoke macros at
run time.  Quite often, the only documented interface to some facility is a
macro.  For instance, if you need to create a constant variable, and the
variable name and/or value is determined at runtime, the only portable way
to do it is:

(defun create-constant (name value)
  (eval `(defconstant ,name ',value)))
-- 
Barry Margolin, Thinking Machines Corp.

······@think.com
{uunet,harvard}!think!barmar
From: Bob Kerns
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Oct25.122834.19088@crl.dec.com>
In article <············@early-bird.think.com>, ······@think.com (Barry Margolin) writes:
> In article <······················@crl.dec.com> ···@crl.dec.com (Bob Kerns) writes:
> >It is so rare that I think it worthwhile to list a few exceptions.
> >
> >* Read-Eval-Print loops.  (That is, tools for interactive use of
> >  the language).
> 
> This includes things like Emacs's M-escape command.
> 
> One other legitimate reason I've seen for using EVAL is to invoke macros at
> run time.  Quite often, the only documented interface to some facility is a
> macro.  For instance, if you need to create a constant variable, and the
> variable name and/or value is determined at runtime, the only portable way
> to do it is:
> 
> (defun create-constant (name value)
>   (eval `(defconstant ,name ',value)))

Of course, I would categorize this as an incorrect
macro interface.  The primitive functionality should be
available directly.

So I wouldn't really term it 'legitimate', just 'necessary
work-around'.

In other words: use it if you have to, but if it's your
code, fix the macro interface instead.
From: Richard Shapiro
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Oct25.143458.13412@arris.com>
In article <······················@crl.dec.com> ···@crl.dec.com (Bob Kerns) writes:
>Generally this can be better done by having a function which
>returns a closure.

Depends on the situation. I agree that closures have many more
respectable uses than EVAL does.

>  The fact that you can do this is a far better
>and far more important argument for using Lisp over C. 

The ability to pass functions around is another good reason to use
Lisp. I don't think it's more important than the equivalence between
data and program (which is what EVAL is all about).

>Note that it *IS* very common to use APPLY. 

True. &Rest arguments wouldn't be very useful without APPLY...

>It's a little strongly stated, but in
>both this statement and mine, the message is "If you're about
>to use EVAL, you should rethink your problem first". `

I'll buy that. It isn't likely that a beginner will need EVAL.

>[a few exceptions]
>* Read-Eval-Print loops.  (That is, tools for interactive use of
>  the language).

This is really the general situation I had in mind. There are many
more interactive uses of the language than the typical top-level
read-eval-print, although I suppose all of them could be considered to
be instantiations of this general prototype. Interactive debuggers
(see below) are one example.

One of the things I use it for is network i/o and pseudo-rpc between
Lisps running on different machines, in circumstances in which real
rpc isn't available. I suppose this could be considered a special case
of read(from net stream)-eval-print(to net stream).

In an application I'm working on now, user-specified forms (another
example of interactive use of the language) are EVAL'd to produce
closures which are then funcalled or mapped over sets of data. I could
not do this in a sufficiently general way without EVAL, or some
equivalent. This is the only use of EVAL in this fairly large system.
But then, I didn't say that any complex application would use EVAL in
*lots* of situations, only that it might very well need to use it
somewhere.

>* Debugging tools.

Another essential use. EVALHOOK is nice in this context too. If you
want to provide an interactive debugger that's friendlier to non-lisp
users than the system debugger, EVAL and EVALHOOK are essential.



EVAL is a very useful function, though I agree that novice Lisp
programmers sometimes misuse it. "Rethink the problem before using
EVAL" seems like good advice to me, certainly better than "if you're
using EVAL you're probably wrong."
From: Kwok K Yum
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Nov1.081849.27574@latcs1.lat.oz.au>
>Bind the variables dynamically:
>> 
>> (let ((a 20)
>>       (b 7))
>>   (declare (special a b))
>>   (eval equation))

>I bet there's a better answer if we knew what he was
>trying to do.  I don't think I've written a call to
>EVAL in 10 years, except as part of a READ-EVAL-PRINT
>loop or similar situation.

My question is:  Is there a way to use EVAL within a lexical environment?
I remember that in a version of Scheme, we can use eval like this:
    (eval <form> <environment>)
Can we have a more elegant way to use the common LISP EVAL as such?

-----------------------------------
Yum
Department of Computer Science and Computer Engineering
La Trobe University
Bundoora, Vic 3083
Australia

Email: ···@latcs1.lat.au.oz
From: Bob Kerns
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Nov5.065444.25536@crl.dec.com>
In article <·····················@latcs1.lat.oz.au>, ···@latcs1.lat.oz.au (Kwok K Yum) writes:
> >Bind the variables dynamically:
> >> 
> >> (let ((a 20)
> >>       (b 7))
> >>   (declare (special a b))
> >>   (eval equation))
> 
> >I bet there's a better answer if we knew what he was
> >trying to do.  I don't think I've written a call to
> >EVAL in 10 years, except as part of a READ-EVAL-PRINT
> >loop or similar situation.
> 
> My question is:  Is there a way to use EVAL within a lexical environment?
> I remember that in a version of Scheme, we can use eval like this:
>     (eval <form> <environment>)
> Can we have a more elegant way to use the common LISP EVAL as such?

There's no way to use EVAL within a lexical environment.
Indeed, the very concept of EVAL is non-lexical, if you
think about the meaning of lexical.

You should view expressions as being closed over the
global lexical environment.  As such, they're pretty
inflexible.  But functions can do what you want.

Consider a situation where you're constructing an expression
like this:

(defun make-equation (a b)
  `(+ (* ,a x) (* ,b y)))

and you're trying to evaluate this
with X = 20 and Y = 7.

There are several things you can do:

You could represent the equation as a function:

(defun make-equation (a b)
  #'(lambda (x y)
      (+ (* a x) (* b y))))

and do

(funcall (make-equation 5 6) 20 7)

This has the advantage that your equation will be evaluated
compiled, which may result in a major speedup.  This will
be particularly important if you are going to evaluate the
equation at a number of points, as in drawing a graph.

Alternatively, you could do something like this:

(eval `(let ((x 20)
	     (y 7))
          ,equation))

That is, LET is how you add variable bindings to the
lexical environment. (Or LAMBDA, but LET is clearer).

(With a little cleverness, you can avoid consing here, but
there's no guarentee that EVAL isn't going to cons anyway).

In general, I would prefer the first solution.  The second
does have the advantage of allowing you to directly manipulate
the equation after its construction, although for some purposes
you could actually pass around both an expression and a function.
From: Mark Friedman
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <MARKF.91Nov6115003@montreux.ai.mit.edu>
In article <·····················@crl.dec.com> ···@crl.dec.com (Bob
Kerns) writes:

   In article <·····················@latcs1.lat.oz.au>,
   ···@latcs1.lat.oz.au (Kwok K Yum) writes:

   > My question is:  Is there a way to use EVAL within a lexical environment?
   > I remember that in a version of Scheme, we can use eval like this:
   >     (eval <form> <environment>)
   > Can we have a more elegant way to use the common LISP EVAL as such?

   There's no way to use EVAL within a lexical environment.
   Indeed, the very concept of EVAL is non-lexical, if you
   think about the meaning of lexical.

Maybe there's no way in Common Lisp, but that doesn't mean that there
is no way no how. As Kwok correctly remembers, in some Schemes (e.g.
MIT Scheme) you can call EVAL with an s-expression and an environment.
This capability, along with a means of capturing the lexical
environment (i.e. first class environments) gives you a means to
evaluate an s-expression in the context of a lexical environment.

You may argue that this is not a good thing and that it plays fast and
loose with the concept of lexical (and many would agreed with you),
but you can't argue that it is impossible or meaningless.

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

·····@zurich.ai.mit.edu
From: Bob Kerns
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <1991Nov12.181448.27935@crl.dec.com>
In article <··················@montreux.ai.mit.edu>, ·····@zurich.ai.mit.edu (Mark Friedman) writes:
> In article <·····················@crl.dec.com> ···@crl.dec.com (Bob
> Kerns) writes:
> 
>    In article <·····················@latcs1.lat.oz.au>,
>    ···@latcs1.lat.oz.au (Kwok K Yum) writes:
> 
>    > My question is:  Is there a way to use EVAL within a lexical environment?
>    > I remember that in a version of Scheme, we can use eval like this:
>    >     (eval <form> <environment>)
>    > Can we have a more elegant way to use the common LISP EVAL as such?
> 
>    There's no way to use EVAL within a lexical environment.
>    Indeed, the very concept of EVAL is non-lexical, if you
>    think about the meaning of lexical.
> 
> Maybe there's no way in Common Lisp, but that doesn't mean that there
> is no way no how. As Kwok correctly remembers, in some Schemes (e.g.
> MIT Scheme) you can call EVAL with an s-expression and an environment.

Indeed, but since he contrasted against Scheme,
I presumed he was asking about Common Lisp.  My
statement has no relevance outside that context.
From: Mark Friedman
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <MARKF.91Nov12182809@montreux.ai.mit.edu>
In article <······················@crl.dec.com> ···@crl.dec.com (Bob Kerns) writes:

>> In article <··················@montreux.ai.mit.edu>, ·····@zurich.ai.mit.edu (Mark Friedman) writes:
>> > In article <·····················@crl.dec.com> ···@crl.dec.com (Bob
>> > Kerns) writes:
>> > 
>> >    There's no way to use EVAL within a lexical environment.
>> >    Indeed, the very concept of EVAL is non-lexical, if you
>> >    think about the meaning of lexical.
>> > 
>> > Maybe there's no way in Common Lisp, but that doesn't mean that there
>> > is no way no how. As Kwok correctly remembers, in some Schemes (e.g.
>> > MIT Scheme) you can call EVAL with an s-expression and an environment.
>> 
>> Indeed, but since he contrasted against Scheme,
>> I presumed he was asking about Common Lisp.  My
>> statement has no relevance outside that context.

Sorry, I overgeneralized your statements about EVAL to apply to the
universe of all concepts, not just the universe of Common Lisp
concepts.

-Mark
--

Mark Friedman
MIT Artificial Intelligence Lab
545 Technology Sq.
Cambridge, Ma. 02139

·····@zurich.ai.mit.edu
From: Bruce Krulwich
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <KRULWICH.91Nov6124854@zowie.ils.nwu.edu>
···@crl.dec.com (Bob Kerns) writes:
    ···@latcs1.lat.oz.au (Kwok K Yum) writes:
    > My question is: Is there a way to use EVAL within a lexical environment?
    
    You should view expressions as being closed over the
    global lexical environment.  As such, they're pretty
    inflexible.  But functions can do what you want.
    
    Consider a situation where you're constructing an expression
    like this:
    
    (defun make-equation (a b)
      `(+ (* ,a x) (* ,b y)))
    
    and you're trying to evaluate this
    with X = 20 and Y = 7.
    
    There are several things you can do:
    
    You could represent the equation as a function:
    
    (defun make-equation (a b)
      #'(lambda (x y)
          (+ (* a x) (* b y))))
    
    and do
    
    (funcall (make-equation 5 6) 20 7)
    
    This has the advantage that your equation will be evaluated
    compiled, which may result in a major speedup.  This will
    be particularly important if you are going to evaluate the
    equation at a number of points, as in drawing a graph.
    
I think that this difference (between evaling and calling closures) is one
that often eludes beginning LISPers, and so it should be reiterated ad
nausium.

EVAL is only necessary if the function(s) being called (or the form of
sub-calls) or the names of the variables being accessed will change at
run-time.  If these are both constant, but just the values of the variables
will change, EVAL is not needed, and a closure will do the job much much
better.  The second form of make-equation above makes a closure, which is then
FUNCALLed (or APPLYed) in an efficient and clean way, without needing EVAL.

In fact, this even applies if the function name will change.  Consider:

> (defun stupid (x y)
    (format t "~%Enter function name: ")
    (let ((fct-sym (read)))
      (funcall (symbol-function fct-sym) x y)))
STUPID
> (stupid 5 6)

Enter function name: +
11
> (stupid 5 6)

Enter function name: *
30
> 

I think that the general rule is that EVAL is only needed if the user is going
to be able to enter the names of variables to evaluate, or to enter the form
of a complex expression to be evaluated.  Even in the second case, EVAL could
be avoided.

The other point to remember is that EVAL is something to avoid whenever you
can.  Code that uses EVAL is much less efficient, mostly due to having to call
the interpreter even when the program is compiled.  Additionally, using EVAL
can cause big problems if you're not careful, more so than dynamic variable
scoping.

Bruce Krulwich
········@ils.nwu.edu

 
From: Jeff Dalton
Subject: Re: using EVAL (was: setqing equations)
Date: 
Message-ID: <5531@skye.ed.ac.uk>
In article <·····················@arris.com> ········@arris.com (Richard Shapiro) writes:
>I understand the pedagogic reasons for saying "Don't use EVAL". But
>this has frequently been transformed into "If you're using EVAL,
>you're probably wrong," which is not only untrue but really very bad
>pedagogy -- when the student does not need to use it, he or she will
>waste time and enery trying to figure out what's "wrong".

In my experience it is especially true for students that almost all
uses of EVAL (except for read-eval-print loops and the like) are
wrong.  Moreover, it's good for students (and others) to spend some
time trying to determine whether they really need EVAL or not.  I find
that most often when someone thinks they need EVAL they are in the
grip of some confusion.

If you're worried about wasting time, I've seen people wast a fair
amount of it trying to debug code that incorrectly used EVAL.

However, I wouldn't recommend saying "If you're using EVAL you're
probably wrong" and leaving it at that.  Some additional explanation
should be supplied, including a list of the common exceptions.

-- jeff