2015-08-28 6 views
9

мне очень интересно, почему это работает (как я бы ожидать, что это после прочтения the documentation on the dot special form):Clojure в дот особая форма странность

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

возвращается:

(true) 

Но это не:

(. clojure.lang.IPersistentMap isInstance {}) 

Я получаю сообщение об ошибке «Нет соответствующего метода: isInstance». Форма точно такая же, как в вызове функции map выше, но за пределами map она не работает. Зачем?

ответ

6

. (dot) sperial form является самым странным из всех. Не уверен, что я собираюсь объяснить это хорошо, но давайте попробуем.

Per docs:

Если первый операнд является символом, который разрешает имя класса, доступ считается к статическому члену названного класса. Обратите внимание, что вложенные классы называются EnclosingClass $ NestedClass, в спецификации JVM. В противном случае предполагается, что это член экземпляра, и первый аргумент оценивается для создания целевого объекта.

Emphasis mine.

Итак, вы попали в первый случай с (. clojure.lang.IPersistentMap isInstance {}) - clojure.lang.IPersistentMap разрешает имя класса, и все выражение считается статическим вызовом метода.

В случае map объект оценивается (часть с акцентом), оценивает объект класса clojure.lang.IPersistentMap перед передачей анонимной функции, и все выражение является вызовом метода экземпляра этого класса.

Таким образом, это сводится к тому, что в одном месте clojure.lang.IPersistentMap используется как символ, который ссылается на имя класса, а в другом - на объект класса.

смотрите также here:

Обратите внимание, что имена классов обычно обозначают объекты класса, а рассматриваются специально в некоторых специальных формах, например, '' и новый.

+3

Это объяснение верно. Я просто добавлю, что вы можете заставить компилятор рассмотреть объект класса, выполнив '(. (Do clojure.lang.IPersistentMap) isInstance {})' (среди прочих способов). Однако специальная форма '.' (И 'new' тоже) очень низкая, и если вы не пишете макросы interop, вы не должны использовать это. Предпочитайте '.member',' constructor.' и 'Class/staticMember' прямое использование' new' и '.'. Если вам любопытно, что вы должны на том, как эти сахаристы образуют макроэкспозицию к формам '.' и' new'. – cgrand