【发布时间】:2017-01-15 21:59:12
【问题描述】:
我试图了解 Clojure 在非尾部位置对 recur 的保护是如何工作的。
如果编写这样的代码,Clojure 会抛出异常:
(def some_var (recur))
但是如果我评估动态创建的代码呢?
(def code '(recur))
(def some_var (eval code))
如果您尝试在 REPL 中运行此代码,它似乎会无限循环。我预计它会引发异常。
我的问题:
Clojure 究竟什么时候检查一个递归是否在尾部位置?
我的第二个代码示例的确切语义是什么(动态执行的非尾部位置的递归)?
【问题讨论】:
-
在您使用
eval的代码中,不会出现任何词法变量,包括recur。你得到的错误清楚地表明它发生在编译时。 -
感谢您的回复!我是否正确理解这一点:如果我
eval代码它会得到它自己的范围,其中 recur 没有定义? -
不完全是..
eval从不使用代码的词法范围。因此(let [x 19] (eval 'x))将评估为全局变量x或抛出x未绑定的错误。因此,您甚至不能从eval中调用本地函数,因为绑定在它被评估的环境中不存在。对于其他词法范围的 lisp 语言也是如此。 -
啊,我明白了,谢谢!那么我的 eval 所做的是在全球环境中评估 recur 吗?你知道这样做的语义是否在某处定义?
-
@Sylwester,
recur是一种特殊形式,所以我认为这与词法绑定无关。
标签: recursion clojure lisp tail-recursion