Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clojure's dot special form weirdness

I'm curious why this works (as I would expect it to after reading the documentation on the dot special form):

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

returns:

(true)

But this does not:

(. clojure.lang.IPersistentMap isInstance {})

I get an error, "No matching method: isInstance". The form is exactly the same as in the map function call above, but outside of map, it doesn't work. Why?

like image 358
at. Avatar asked Aug 28 '15 08:08

at.


1 Answers

The . (dot) sperial form is the weirdest of them all. Not sure if I'm going to explain it well, but let's try.

Per docs:

If the first operand is a symbol that resolves to a class name, the access is considered to be to a static member of the named class. Note that nested classes are named EnclosingClass$NestedClass, per the JVM spec. Otherwise it is presumed to be an instance member and the first argument is evaluated to produce the target object.

Emphasis mine.

So you have hit the first case with (. clojure.lang.IPersistentMap isInstance {}) - clojure.lang.IPersistentMap resolves to class name and the whole expression is assumed to be a static method call.

In the map case the symbol is evaluated (the part with emphasis), evaluates to clojure.lang.IPersistentMap class object before being passed to the anonymous function and the whole expression is an instance method call on that class.

So it boils down to the fact that in one place the clojure.lang.IPersistentMap is being used as a symbol that refers to a class name and in the other as something that evaluates to a class object.

Also look here:

Note that class names normally denote class objects, but are treated specially in certain special forms, e.g. '.' and new.

like image 52
soulcheck Avatar answered Oct 18 '22 16:10

soulcheck