ThePiercingPrince
ThePiercingPrince

Reputation: 1921

Eval in Scheme accessing lexical variables

(define x 44) (define y 25)
(let ((x 12) (y 23)) (if #f (eval x) (eval y)))

The above code returns 25, as eval uses global variables. How to create something similar to eval but looks for local variables when it sees variable references?

Upvotes: 0

Views: 262

Answers (3)

Loïc Faure-Lacroix
Loïc Faure-Lacroix

Reputation: 13600

There is an other possible way to do it. I can't really do it for the moment but it can be done using an explicit environment.

If you look at the signature of eval, you'll see that it accepts a third parameter.

http://wiki.call-cc.org/man/4/Unit%20eval#eval

[procedure] (eval EXP [ENVIRONMENT])

It might not be present on all scheme and even in chicken-scheme, this third parameter is almost useless at the moment.

What you could do is something like this.

(define x 25)
(define y 10)

(let* ((x 23)
       (y 21)
       (env (current-environment))

  (print (eval '(x y) env)))

This sounds good in words but the current-environment function is most likely to be the missing. I believe in gambit it is quite possible to do but even in chicken the environments module is deprecated and there is no alternative that I know of.

Upvotes: 1

DaoWen
DaoWen

Reputation: 33019

Not sure what Scheme you're using, but in Racket I get a different answer:

> (define x 44)
> (define y 25)
> (let ((x 12) (y 23)) (if #f (eval x) (eval y)))
23

This is the behavior I'd expect in any Scheme or Lisp. I think you meant to quote the x and y in eval:

> (let ((x 12) (y 23)) (if #f (eval 'x) (eval 'y)))
25

Now we get the result you were expecting. If you don't quote the argument to eval, then it gets evaluated and then passed in to eval as a value instead of a form. In the previous case, you end up with (eval y) --> (eval 23) --> 23. However, you can take advantage of this using quasi-quoting, selectively unquoting variables that you want evaluated in the current scope:

> (let ((x 12) (y 23)) (eval `(if #f ,x ,y)))
23

Upvotes: 2

C. K. Young
C. K. Young

Reputation: 223003

Most Scheme implementations do not support references to lexical variables in their eval. As a special case, Guile has local-eval in its (ice-9 local-eval) module, which does support lexical variables.

Upvotes: 2

Related Questions