Scheme中的Eval访问词法变量

时间:2013-11-17 02:58:59

标签: scheme lisp eval

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

上面的代码返回25,因为eval使用全局变量。如何创建类似于eval的东西,但在看到变量引用时查找局部变量?

3 个答案:

答案 0 :(得分:2)

大多数Scheme实现不支持在eval中引用词法变量。作为一个特例,Guile在其(ice-9 local-eval)模块中有local-eval,它支持词法变量。

答案 1 :(得分:2)

不确定您使用的是哪种方案,但在Racket中我得到了不同的答案:

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

这是我在任何Scheme或Lisp中所期望的行为。我想你的意思是引用x中的yeval

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

现在我们得到你期待的结果。如果您没有将参数引用到eval,那么它将被评估,然后作为值而不是表单传递给eval。在之前的案例中,您最终得到(eval y) - > (eval 23) - > 23.但是,您可以使用quasi-quoting来利用此功能,有选择地取消在当前范围内评估的变量:

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

答案 2 :(得分:1)

还有另一种可能的方法。我暂时无法做到这一点,但可以使用明确的环境来完成。

如果您查看eval的签名,您会看到它接受第三个参数。

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

[procedure] (eval EXP [ENVIRONMENT])

它可能不存在于所有方案中,即使在鸡计划中,这第三个参数目前几乎无用。

你能做的就是这样。

(define x 25)
(define y 10)

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

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

这听起来不错,但current-environment功能很可能是缺失的。我相信它很有可能,但即使在鸡肉中,环境模块也被弃用了,而且我知道没有替代品。