5

我惊讶地发现在 Clojure 中alpha 转换是不安全的:

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上的版本。

4

2 回答 2

6

根据文档,您不能隐藏特殊形式:

一个符号被解析:

  • 如果它是命名空间限定的,则该值是由符号命名的全局变量的绑定值。如果没有由符号命名的全局变量,或者如果引用指向不同命名空间中的非公共变量,则会出现错误。
  • 如果它是包限定的,则值是由符号命名的 Java 类。如果没有由符号命名的类,则这是一个错误。
  • **否则,不合格,适用以下第一项:
    1. 如果它命名了一个特殊的形式,它被认为是一个特殊的形式,并且必须相应地使用。**
    2. 在当前命名空间中进行查找以查看是否存在从符号到类的映射。如果是这样,则认为该符号命名了一个 Java 类对象。请注意,类名通常表示类对象,但会以某些特殊形式进行特殊处理,例如“.”。和新的。
    3. 如果在本地范围内(即在函数定义中),则进行查找以查看它是否命名了本地绑定(例如,函数参数或让绑定名称)。如果是,则该值是本地绑定的值。
    4. 在当前命名空间中进行查找以查看是否存在从符号到 var 的映射。如果是这样,则该值是该符号所引用的 var 的绑定值。
    5. 这是一个错误。

而且我不确定,但我将这段话(来自同一页)解释为您不能隐藏宏:

宏是操作表单的函数,允许进行语法抽象。如果调用的运算符是一个符号,它命名了一个作为宏函数的全局变量,则调用该宏函数并传递未计算的操作数形式。然后在其位置评估宏的返回值。

如果运算符不是特殊形式或宏,则该调用被视为函数调用。

于 2012-08-16T13:29:44.440 回答
3

前两个对我来说都评估为 5(Eclipse / 逆时针 REPL 中的 Clojure 1.4)。如果您获得 3,我怀疑 Try Clojure 中存在错误。

您应该能够在本地隐藏函数和宏名称(尽管这通常不是一个好主意,因为它可能会导致一些微妙和令人困惑的错误!)。

第三个不起作用,因为def它是一种特殊形式。特殊形式从 Clojure 阅读器和/或编译器获得特殊处理,因此您不能隐藏它们。

于 2012-08-16T13:26:30.753 回答