From: Jeremy Smith
Subject: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <Xns973BDD33EC19Bjeremyalansmithsofth@80.5.182.99>
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:

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?

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!

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.

Thanks for any help,

Jeremy.

From: Kaz Kylheku
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <1135895978.803972.101550@z14g2000cwz.googlegroups.com>
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.
From: Jeremy Smith
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <Xns973C1D0AA1D9Djeremyalansmithsofth@62.253.170.163>
"Kaz Kylheku" <········@gmail.com> wrote in
·····························@z14g2000cwz.googlegroups.com: 

> A lexical scope is "baked" at compile time.

I understand.

> 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.

It doesn't sound like I can do it from a text string, but I'll look into 
it.

>> 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.

It's not in a package, but the code to eval the read-from-string is in a 
macro. I guess I'm way in over my head and need to simplify things a bit 
and re-read the chapters in Practical Common Lisp on Macros (which I am 
doing).

> 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.

This sounds like a great idea.
 
> You don't have to eval the "naked" forms that you are reading from the
> description language files.

I didn't know this could be done that easily. Your use of commas in that 
code sample are new to me. Thanks for the information, and I'll try your 
example, it should work well.

Happy New Year,

Jeremy.
From: Wade Humeniuk
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <EyZsf.13421$6K2.5772@edtnps90>
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:
> 
> 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?
> 

For the above example simply do,

(let ((left 5) (top 10))
   (eval `(let ((left ,left) (top ,top))
            (eql left (margin top 20)))))

If you want to continue to use read-from-string like the
above example you can do,

(let ((left 5) (top 10))
   (eval `(let ((left ,left) (top , top))
            ,(read-from-string "(eq left (margin top 20))"))))

Wade
From: Tin Gherdanarra
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <41j4tfF1cpgeiU1@individual.net>
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:

(eval) gets its own scope. It would be nice if you could pass
the current environment with all its local variables to eval.
However, I don't know a way to do this. What you might use is
closures, but they more or less just replace global variables
with global functions.

(let ((left 5)) (top 10))
   (defun get-left nil left)
   (defun get-top nil top)
   (eval (read-from-string "(eq left top)")))

> 
> 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?

I remember a scheme where you could do this with eval-env or something
and pass the environment in the second parameter. You could write your
own eval-env. Not trivial, though.

> 
> 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.

You could make lisp your declaration language. Syntax sucks anyway.
If your program is used and extended for a long time, the syntax
will grow. After a few years today's improvisations will haunt
you and will force you and your users to live with cruft.
From: Jeremy Smith
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <Xns973C3240720Djeremyalansmithsofth@80.5.182.99>
Tin Gherdanarra <···········@gmail.com> wrote in
····················@individual.net: 

> 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:
> 
> (eval) gets its own scope. It would be nice if you could pass
> the current environment with all its local variables to eval.
> However, I don't know a way to do this.

Ah, okay, thanks for the confirmation.

> What you might use is
> closures, but they more or less just replace global variables
> with global functions.

I understand the idea. I think the best thing will be something in one of 
the other posts, about eval'ing the code with the variables and initial 
values inserted before the code.

> (let ((left 5)) (top 10))
>    (defun get-left nil left)
>    (defun get-top nil top)
>    (eval (read-from-string "(eq left top)")))

>> 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.
> 
> You could make lisp your declaration language. Syntax sucks anyway.
> If your program is used and extended for a long time, the syntax
> will grow. After a few years today's improvisations will haunt
> you and will force you and your users to live with cruft.

I suppose you're saying to use Lisp as the language. That sounds like a 
good idea, partly because it has minimal syntax, as long as I can get 
around the problem of malicious code. Also, it's not necessarily "today's 
improvisations" - I'm just experimenting at the moment, and nothing is 
set in stone. The basic idea is to get it working first. Also, I'm going 
to read On Lisp once it works enough to be improved.

Thanks for your help, have a happy new year!

Cheers,

Jeremy.
From: Pascal Costanza
Subject: Re: Quick question: eval and read-from-string scoping
Date: 
Message-ID: <41januF1ci42pU1@individual.net>
Jeremy Smith wrote:

> 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?

This isn't specified in ANSI Common Lisp. Some CL implementations allow 
this as an extension. For example, clisp allows you to use first-class 
lexical environments in interpreted code - see 
http://clisp.cons.org/impnotes.html#eval-environ

Some other Lisp dialects provide this as well, for example OpenLisp, as 
do some Scheme implementations.

It's not specified in ANSI Common Lips because it prevents important 
optimizations. In many cases, you can find workarounds.


Pascal

-- 
My website: http://p-cos.net
Closer to MOP & ContextL:
http://common-lisp.net/project/closer/