Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Alternatives to EVAL

39 views
Skip to first unread message

David E. Young

unread,
Mar 31, 2000, 3:00:00 AM3/31/00
to
Greetings. I've read that if EVAL is used explicitly within a program,
it probably indicates poor design. We've a situation where we're getting
Lisp forms via a CORBA invocation and must somehow evaluate them within
the context of a particular package. As a rough prototype, we've
writting something like this:

(defmacro eval-from-string (str)
`(eval (read-from-string ,str))

However, since I certainly want to avoid poor constructs, and in the
interest of becoming a better Lisp developer, I'm soliciting
alternatives. I have Graham's books, but I'm currently at home and don't
have them handy. Thanks much.


--
David E. Young
Fujitsu Network Communications "The fact that ... we still
(d...@nc.fnc.fujitsu.com) live well cannot ease the pain of
feeling that we no longer live nobly."
-- John Updike
"Programming should be fun,
programs should be beautiful"
-- P. Graham


David E. Young

unread,
Mar 31, 2000, 3:00:00 AM3/31/00
to
"David E. Young" wrote:

> Greetings. I've read that if EVAL is used explicitly within a program,
> it probably indicates poor design. We've a situation where we're getting
> Lisp forms via a CORBA invocation and must somehow evaluate them within
> the context of a particular package. As a rough prototype, we've
> writting something like this:
>
> (defmacro eval-from-string (str)
> `(eval (read-from-string ,str))
>

Following up my own post, I forgot to mention that typically, the form sent
across the wire (and handed to eval) will be a macro. Sorry for the
omission.

Mike McDonald

unread,
Apr 1, 2000, 3:00:00 AM4/1/00
to
In article <38E53B02...@mindspring.com>,

"David E. Young" <you...@mindspring.com> writes:
> Greetings. I've read that if EVAL is used explicitly within a program,
> it probably indicates poor design.

It might be an indicator but it's not an obsolute either.

> We've a situation where we're getting
> Lisp forms via a CORBA invocation and must somehow evaluate them within
> the context of a particular package. As a rough prototype, we've
> writting something like this:
>
> (defmacro eval-from-string (str)
> `(eval (read-from-string ,str))

Calling EVAL when you want something evaluated is a perfectly rational and
justifiable thing to do. You may want to add error handling though, for both
the READ-FROM-STRING and the EVAL.

Mike McDonald
mik...@mikemac.com

Barry Margolin

unread,
Apr 1, 2000, 3:00:00 AM4/1/00
to
In article <38E53B02...@mindspring.com>,

David E. Young <you...@mindspring.com> wrote:
>Greetings. I've read that if EVAL is used explicitly within a program,
>it probably indicates poor design.

This mainly applies to cases where the program creates an expression and
then EVALs it. It should probably use things like function objects and
function composition.

However, if it's receiving the expression from an external source, it's
normal. For instance, the fact that the read-eval-print loop uses EVAL
doesn't indicate a misdesign of the read-eval-print loop -- that's
precisely what EVAL is for.

--
Barry Margolin, bar...@bbnplanet.com
GTE Internetworking, Powered by BBN, Burlington, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

Christopher Browne

unread,
Apr 1, 2000, 3:00:00 AM4/1/00
to
Centuries ago, Nostradamus foresaw a time when David E. Young would say:

>Greetings. I've read that if EVAL is used explicitly within a program,
>it probably indicates poor design. We've a situation where we're getting

>Lisp forms via a CORBA invocation and must somehow evaluate them within
>the context of a particular package. As a rough prototype, we've
>writting something like this:
>
> (defmacro eval-from-string (str)
> `(eval (read-from-string ,str))
>
>However, since I certainly want to avoid poor constructs, and in the
>interest of becoming a better Lisp developer, I'm soliciting
>alternatives. I have Graham's books, but I'm currently at home and don't
>have them handy. Thanks much.

Part of the secret is in knowing when to break the rules...

There is always some point at which forms need to be (eval)ed.

It tends to be preferred to do this at compile time, and thus avoid
the resultant security and runtime-speed issues.

If the forms are actually crossing over via CORBA, then you indeed do
need to have an eval, and while there could be some quibbling over
precisely *where* it should take place, it sure sounds like you've got
it in something *resembling* the right place.

You might want to provide a "hook" to allow some processing on the
strings before they get (eval)led so that there's some validation of
correctness/safeness. Rather resembling the common CGI step where
strings are pre-processed to prevent someone from transmitting "evil
things" and breaking security.
--
You know how most packages say "Open here". What is the protocol if
the package says, "Open somewhere else"?
cbbr...@hex.net- <http://www.ntlug.org/~cbbrowne/lisp.html>

Tom Breton

unread,
Apr 1, 2000, 3:00:00 AM4/1/00
to
"David E. Young" <you...@mindspring.com> writes:

> Greetings. I've read that if EVAL is used explicitly within a program,
> it probably indicates poor design.

I wouldn't say that. Using eval *gratuitously* indicates poor design,
because it adds an extra level of indirection without accomplishing
anything. But where the extra indirection is helpful, by all means
use it. Lisp is meant to do powerfully expressive things like that.
That's why eval is there.

>We've a situation where we're getting
> Lisp forms via a CORBA invocation and must somehow evaluate them within
> the context of a particular package. As a rough prototype, we've
> writting something like this:
>
> (defmacro eval-from-string (str)
> `(eval (read-from-string ,str))


Ordinarily I'd ask why you are writing a string instead of directly
writing a sexp. But since you tell me that's the only form you can
get the forms in, then ISTM your solution is fine.

I do wonder if you really want to use a macro rather than a function.
Macros are just Lisp acting as its own preprocessor. *Are* these
forms actually something you're preprocessing?

> have them handy. Thanks much.

You're quite welcome.

--
Tom Breton, http://world.std.com/~tob
Not using "gh" since 1997. http://world.std.com/~tob/ugh-free.html
Rethink some Lisp features, http://world.std.com/~tob/rethink-lisp/index.html

David E. Young

unread,
Apr 1, 2000, 3:00:00 AM4/1/00
to
Tom Breton wrote:

> "David E. Young" <you...@mindspring.com> writes:
>
> > Greetings. I've read that if EVAL is used explicitly within a program,
> > it probably indicates poor design.
>
>

> I do wonder if you really want to use a macro rather than a function.
> Macros are just Lisp acting as its own preprocessor. *Are* these
> forms actually something you're preprocessing?
>

Hey Tom. The forms coming across the wire are indeed macro calls exported by a
third-party package. Right now, that's the way they must remain, so the
concensus here is that EVAL in this situation is an appropriate use. Thanks to
everyone who replied.

Regards,

Rob Warnock

unread,
Apr 2, 2000, 4:00:00 AM4/2/00
to
David E. Young <you...@mindspring.com> wrote:
+---------------

| The forms coming across the wire are indeed macro calls exported by a
| third-party package. Right now, that's the way they must remain, so the
| concensus here is that EVAL in this situation is an appropriate use.
+---------------

Well, if *all* the forms coming across the wire are indeed "macro calls",
then for safety (*and* speed!) you might want to do you own "expansion" of
the "macros". That is, simply put a function to process each form into a
hash table indexed by the "macro" keyword [car of the form]. The per-form
functions can always call EVAL on certain sub-forms if they really, really
need to, but I'll bet that most (if not all) of the time the rest of each
form is just "data" to the per-form function.

If your application *can* fit into this model...

1. It's a lot cleaner than using EVAL, since you don't have to worry
about confusions between "macro-expand time" and run-time;

2. It's a lot *faster* than using EVAL (you don't go through the entire
interpreter);

3. It's a lot *safer* than using EVAL, since only pre-loaded handlers
can be called (especially if you turn off *READ-EVAL*).


-Rob

-----
Rob Warnock, 41L-955 rp...@sgi.com
Applied Networking http://reality.sgi.com/rpw3/
Silicon Graphics, Inc. Phone: 650-933-1673
1600 Amphitheatre Pkwy. PP-ASEL-IA
Mountain View, CA 94043

Erik Naggum

unread,
Apr 2, 2000, 4:00:00 AM4/2/00
to
* "David E. Young" <you...@mindspring.com>

| I've read that if EVAL is used explicitly within a program, it probably
| indicates poor design.

the probability is not 1.0, however. using EVAL in servers or programs
that accept input from users or agents of users for the express purpose
of evaluation in the Lisp world is good design -- reinventing your own
EVAL at this point is poor design.

#:Erik

Scott L. Burson

unread,
Apr 4, 2000, 3:00:00 AM4/4/00
to
"David E. Young" wrote:
>
> Hey Tom. The forms coming across the wire are indeed macro calls exported by a

> third-party package. Right now, that's the way they must remain, so the
> concensus here is that EVAL in this situation is an appropriate use.

Hmm, as a protocol design, this makes me a little nervous.

One thing you should definitely do, if you aren't already, is to specifically
bind *PACKAGE* across the READ-FROM-STRING call to a package that contains all
the symbols you need. This will prevent your code from breaking if someone sets
the package to something weird.

(Digression: I learned my lesson on this the hard way. Years ago, on a Lisp
Machine, I was hacking something for which I needed a package that did not
inherit any symbols from any other package. When I set *PACKAGE* to this
package, I discovered that the LispM could no longer access its file server
(!). After a considerable amount of poking around, I found the problem: the
Chaos NFILE protocol relied on the server sending file properties to the client
in the form of printed list structure, which contained, among other things, the
symbol NIL. With *PACKAGE* bound to my weird package, the client's
READ-FROM-STRING got the wrong NIL, thus breaking the protocol.)

I would additionally suggest going a bit further and making a package that
contains *only* the symbols you will need to read. This will limit what the
incoming forms can do when EVALed... which would make me a lot more comfortable
with this design.

-- Scott

Erik Naggum

unread,
Apr 4, 2000, 3:00:00 AM4/4/00
to
* Scott L. Burson

| I would additionally suggest going a bit further and making a package
| that contains *only* the symbols you will need to read. This will limit
| what the incoming forms can do when EVALed... which would make me a lot
| more comfortable with this design.

it's even a little worse than you sketch out. ideally, you should be
able to force intern not to intern, i.e. to have read call find-symbol
and barf on uninterned symbols. ideally, you should be able to force the
symbol-reader to barf on _any_ package specification other than those you
have specified. neither of these are possible in fully conforming code.

#:Erik

David E. Young

unread,
Apr 5, 2000, 3:00:00 AM4/5/00
to
"Scott L. Burson" wrote:

> "David E. Young" wrote:
> >
> > Hey Tom. The forms coming across the wire are indeed macro calls exported by a
> > third-party package. Right now, that's the way they must remain, so the
> > concensus here is that EVAL in this situation is an appropriate use.
>
> Hmm, as a protocol design, this makes me a little nervous.
>
> One thing you should definitely do, if you aren't already, is to specifically
> bind *PACKAGE* across the READ-FROM-STRING call to a package that contains all
> the symbols you need. This will prevent your code from breaking if someone sets
> the package to something weird.
>

Yes, this is precisely what I'm doing (after experiencing a problem similar to that
described in your LispM annecdote). Appreciate the thoughts.

0 new messages