(define x 44) (define y 25)
(let ((x 12) (y 23)) (if #f (eval x) (eval y)))
上面的代码返回25,因为eval使用全局变量。如何创建类似于eval的东西,但在看到变量引用时查找局部变量?
答案 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
中的y
和eval
:
> (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
功能很可能是缺失的。我相信它很有可能,但即使在鸡肉中,环境模块也被弃用了,而且我知道没有替代品。