Reputation: 5309
While testing the java interoperability, I executed - (macroexpand-1 '(.toUpperCase "deepak"))
and the output was (. "deepak" toUpperCase)
Now, I came to know that .
performs some sort of operation.
When I printed the doc
for .
using (clojure.repl/doc .)
, I got the output as
-------------------------
.
(.instanceMember instance args*)
(.instanceMember Classname args*)
(Classname/staticMethod args*)
Classname/staticField
Special Form
The instance member form works for both fields and methods.
They all expand into calls to the dot operator at macroexpansion time.
I could not understand the pattern of parameters the .
expects. For example - .instanceMember
How does the parameters "deepak"
and toUpperCase
map to the above pattern when we execute (. "deepak" toUpperCase)
?
What is instance name, class name, and instance for the expression - (. "deepak" toUpperCase)
?
Upvotes: 1
Views: 96
Reputation: 807
The docstring is potentially misleading - which may be the cause of your confusion.
There are two different ways to access Java interop with the "dot" form. There is Member access (.toUpperCase "deepak")
, and there is the dot special form (. "deepak" toUpperCase)
. The docstring you showed is for Member access (.toUpperCase "deepak")
, whereas the form you were looking at is the dot special form (. "deepak" toUpperCase)
. It is preferable that you use the Member access style of interop in most cases. Internally, the Member access style of interop is translated into the dot special form (as you found by doing the macroexpand-1
).
So, in the case of (.toUpperCase "deepak")
, using the docstring for Member access (.instanceMember instance)
, the correspondences are:
instanceMember
maps to toUpperCase
instance
maps to "deepak"
Upvotes: 0
Reputation: 29958
You are delving into internal details of Clojure here. This is normally not required (& usually not useful).
An expression like (.toUpperCase "deepak")
calls the method "toUpperCase" on the java.lang.String object "deepak"
, eg
(.toUpperCase "deepak") => "DEEPAK"
The compiler translates the above internally into
(. "deepak" toUpperCase) => "DEEPAK"
which of course has the same result. You can find more information in the docs for The Dot Special Form
The docs are sometimes hard to read, but you can decipher it with a little pattern matching. In the above example, .toUpperCase
is ".instanceMember" and "deepak"
is the "instance" that is of type java.lang.String
.
For (.getName String)
, the symbol String
(shorthand for java.lang.String
) is the "Classname". In the docs args*
is a regex-like shorthand for saying zero-or-more arguments may be needed (the previous examples have zero args required).
Was there something else you wanted to accomplish?
P.S.
"When in doubt, ask the compiler."
I struggled with similar questions when I was learning Clojure, getting confused by docs & books that were incomplete or ambiguous. I later learned it was MUCH faster & much more educational to try simple experiments to fill in the blanks.
I think simple code snippets are easier/faster than the REPL:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(dotest
(spyx (.toUpperCase "deepak"))
(spyx (. "deepak" toUpperCase))
(spyx (type "deepak"))
)
using my favorite template project, with result
-----------------------------------
Clojure 1.10.3 Java 17.0.1
-----------------------------------
Testing tst.demo.core
(.toUpperCase "deepak") => "DEEPAK"
(. "deepak" toUpperCase). => "DEEPAK"
(type "deepak") => java.lang.String
Also,
(.getName String) => "java.lang.String"
(.getName java.lang.String). => "java.lang.String"
Note carefully the presence/absence of double-quotes.
Upvotes: 3