So I thought it would be a nice idea to name a function that calculates the exponential ^
, but it seems like the caret actually does something special, as the Clojure REPL generates an error when evaluating '^
. Googling mostly gave me this, so I was wondering what the actualy use for the caret in Clojure is.
(Also, would it be possible after all to name a function ^
?)
There may be some confusion here from the different usages of the term "symbol" in Common Lisp and in Clojure. In Common Lisp, a "symbol" is a location in memory, a place where data can be stored. The "value" of a symbol is the data stored at that location in memory. In Clojure, a "symbol" is just a name.
Clojure (/ˈkloʊʒər/, like closure) is a dynamic and functional dialect of the Lisp programming language on the Java platform. Like other Lisp dialects, Clojure treats code as data and has a Lisp macro system.
^
is "the meta character" it tells the reader to add the symbol starting with ^
as metadata to the next symbol (provided it is something that implements IMetas)
user=> (def x ^:IamMeta [1 2 3]) #'user/x user=> x [1 2 3] user=> (meta x) {:tag :IamMeta} user=>
You can learn a lot about how clojure works under the hood by looking at the meta
of things, for instance functions:
user=> (meta foo) {:ns #<Namespace user>, :name foo, :file "NO_SOURCE_PATH", :line 5, :arglists ([s])}
this is very often used for type hints
(defn foo [^String s] (.charAt s 1))
it is generally a good idea to turn on reflection warnings (set! *warn-on-reflection* true)
and then add type hints until the warnings go away. without these Clojure will look up the type of the function operands at run-time, which saves you the trouble of fussing with types though at a slight cost.
PS: My next favorite reader character is the "dispatch" character #
, it is well worth learning about it next :)
PPS: this is different in clojure 1.2.x vs clojure 1.3.x in Clojure 1.2.1 metadata does not compose when you use the meta-character:
user=> (def foo ^:foo ^:bar [1 2 3]) #'user/foo user=> (meta foo) {:tag :foo}
and in 1.3 it "does the right thing" and also keywords are options instead of "tags":
user=> (def foo ^:foo ^:bar [1 2 3]) #'user/foo user=> (meta foo) {:foo true, :bar true}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With