2015-08-28 39 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