Re: Quick question: eval and read-from-string scoping
- From: "Kaz Kylheku" <kkylheku@xxxxxxxxx>
- Date: 29 Dec 2005 14:39:38 -0800
Jeremy Smith wrote:
> Hi,
>
> When I run this code in CLisp:
>
> (let ((left 5) (top 10))
> (eval(read-from-string "(eq left (margin top 20))")))
>
> When executed, it complains that "*** - EVAL: variable left has no
> value". At first I wondered why the local variables were not in scope for
> the eval'd code and was going to post, but I found this thread:
The evaled string isn't code, it's a character string that only becomes
data inside READ-FROM-STRING, which only becomes code inside EVAL.
A lexical scope is "baked" at compile time.
> http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/846c4f
> 53e91ef251/69239105712fed0d?lnk=st&q=lisp+eval+global+variables&rnum=2#
> 69239105712fed0d
>
> And now I realise that eval is like a function, and local variables are
> not passed from function to function. So the question is revised: How do
> I pass variables to code executed by eval without declaring them as
> special?
You can eval a lambda expression to produce a function. That function
can take parameters. You can funcall the resulting function, and use
local variables as arguments.
> I realise that special variables can be re-defined using 'let' and they
> are passed down to any functions called by the parent, but this doesn't
> appear to be working when calling eval. Code run by eval cannot see the
> re-bound special variables. Odd!
It does work with eval. Maybe you have a package-related problem.
Perhaps your code (the function, and the special variables, and all) is
defined in some package, but then when the function is called called,
READ-FROM-STRING is in a different package.
E.g.
(in-package 'my-package)
(defvar *special* 42)
(defun eval-over-special ()
(let ((*special* 2))
(eval (read-from-string "(+ *special* *special*)"))))
The special variable here is actually MY-PACKAGE::*SPECIAL*. But the
symbol *SPECIAL* that is read from the string will be interned in
whatever package is current when MYPACKAGE::EVAL-OVER-SPECIAL is
called.
> Finally, my reasons for knowing this is that I am implementing a small
> description language for OCR (optical character recognition) software but
> I'm implementing it in Lisp before I write a parser, so I 'eval' the
> descriptions as if read in from a text file. The reason I need to be able
> to pass data to the eval'd code is because they are the attributes of the
> current character object (such as top,bottom,left,right) and thus should
> not be global.
That doesn't explain why these attributes have to be direct references
to lexical variables in your evaluator. You can transform the code
before you EVAL it, turning it into functions that take parameters.
E.g. if CODE contains the source code of an expression that is known to
refer to the variables A, B and C, you can do this:
(eval `(let ((a ,value-for-a) (b ,value-for-b) (c ,value-for-c))
,code))
In other words, build up a larger piece of source code which
establishes bindings for A, B and C, and whose body is that expression.
The initial values for these variables are stuck in via backquote
substitution.
You don't have to eval the "naked" forms that you are reading from the
description language files.
.
- Follow-Ups:
- Re: Quick question: eval and read-from-string scoping
- From: Jeremy Smith
- Re: Quick question: eval and read-from-string scoping
- References:
- Quick question: eval and read-from-string scoping
- From: Jeremy Smith
- Quick question: eval and read-from-string scoping
- Prev by Date: Re: Quick question: eval and read-from-string scoping
- Next by Date: Re: Lisp executables?
- Previous by thread: Re: Quick question: eval and read-from-string scoping
- Next by thread: Re: Quick question: eval and read-from-string scoping
- Index(es):
Relevant Pages
|