2015-08-28 58 views
9

我很好奇,为什么这个工作(如我所期望它读取the documentation on the dot special form后):Clojure的点特殊形式的怪事

(map #(. % isInstance {}) [clojure.lang.IPersistentMap]) 

回报:

(true) 

但这并不:

(. clojure.lang.IPersistentMap isInstance {}) 

我得到一个错误,“没有匹配的方法:isInstance”。该表格与上面的map函数调用完全相同,但在map之外,它不起作用。为什么?

回答

6

.(点)sperial形式是他们所有人中最奇怪的。不知道我是否要解释清楚,但让我们试试。

docs

如果第一个操作数是解析为一个类名的象征,访问被认为是于指定类的静态成员。请注意,根据JVM规范,嵌套类被命名为EnclosingClass $ NestedClass。 否则它被认为是一个实例成员,并且第一个参数被评估为产生目标对象。

强调我的。

因此,您已经打到第一个案例(. clojure.lang.IPersistentMap isInstance {}) - clojure.lang.IPersistentMap解析为类名称,整个表达式被假定为静态方法调用。

map的情况下,评估符号(重点部分),在传递给匿名函数前评估为clojure.lang.IPersistentMap类对象,并且整个表达式是该类的实例方法调用。

因此,归结起来,在一个地方,clojure.lang.IPersistentMap被用作引用类名称的符号,另一个用作评估类对象的东西。

也期待here

注意,类名通常表示类对象,但在某些特殊的形式,例如特殊处理''和新的。

+3

这个解释是正确的我只是补充说你可以强制编译器通过执行'(。(do clojure.lang.IPersistentMap)isInstance {})'(以及其他方式)来考虑类对象。 然而'''特殊形式(和'new')的级别非常低,除非你正在编写一些互操作宏,否则你不应该使用它。优先使用'.member','constructor.'和'Class/staticMember'直接使用'new'和'.'。如果你很好奇,你应该看看这些糖化形式是如何膨胀为“。”和“新”的形式的。 – cgrand