我很惊讶地发现alpha-conversion在Clojure中并不安全:
Clojure> ((fn [o] (o 3 2)) +)
5
Clojure> ((fn [or] (or 3 2)) +)
3
Clojure> ((fn [def] (def 3 2)) +)
java.lang.RuntimeException: First argument to def must be a Symbol
(我预计所有三个片段都要评估为5)。
当涉及阴影和宏以及特殊形式时,符号解析的规则是什么?
我正在使用Try Clojure上的版本。
答案 0 :(得分:6)
符号已解决:
- 如果它是名称空间限定的,则该值是由符号命名的全局变量的绑定值。如果有的话,这是一个错误 不是由符号命名的全局var,或者引用是否为a 不同命名空间中的非公共var。
- 如果它是包限定的,则值是由符号命名的Java类。如果没有符号命名的类,则会出错。
- **否则,它不合格,并且以下第一项适用:
- 如果它命名为特殊表格,则视为特殊表格,必须相应使用。**
- 在当前命名空间中完成查找,以查看是否存在从符号到类的映射。如果是,则考虑符号 命名一个Java类对象。请注意,类名通常表示类 物体,但特殊处理的特殊形式,例如'' 和新的。
- 如果在本地范围内(即在函数定义中),则进行查找以查看它是否命名本地绑定(例如函数参数) 或者让自己的名字)。如果是,则该值是本地的值 结合。
- 在当前命名空间中完成查找,以查看是否存在从符号到var的映射。如果是,则该值是该值 绑定由符号引用的var。
- 这是一个错误。
而且我不确定,但是我将这一段(从同一页面)解释为意味着你不能影响宏:
宏是操纵表单的函数,允许语法 抽象。如果呼叫的运营商是命名全局的符号 var是一个宏函数,调用宏函数并且是 通过了未评估的操作数表格。宏的返回值是 然后在其位置进行评估。
如果运营商不是特殊表格或宏,则会考虑通话 一个函数调用。
答案 1 :(得分:3)
前两个对我来说都评价为5(Eclipse中的Clojure 1.4 /逆时针REPL)。如果你得到3,我怀疑Try Clojure中有一个错误。
你应该能够在本地影响函数和宏名称(虽然它通常不是一个好主意,因为它可能导致一些微妙和令人困惑的错误!)。
第三个不起作用,因为def
是special form。特殊形式从Clojure阅读器和/或编译器获得特殊处理,因此您无法遮蔽它们。