On Jun 21, 2009, at 9:51 AM, Ratandeep Ratti wrote:
Why are these different? user> #^String "hello" ; Evaluation aborted.
#^ is a reader macro for applying metadata to the next object read. The metadata applied is always a map. If a sequence of characters (<chars>) appears after #^: #^<chars>, it is interpreted as a shorthand notation for #^{:tag <chars>}.
The reader can only apply metadata to objects that implement the Java interface IMeta. When I try your example, I get:
user=> #^String "hello"java.lang.IllegalArgumentException: Metadata can only be applied to IMetas
While it might be useful to apply metadata to strings, we can't because Clojure strings are Java Strings and Java Strings are final and don't implement IMeta.
(def a "hello") #'user/a user> #^String a "hello"
Here the reader was asked to apply the map {:tag String} as metadata to the symbol a as it was read in. Symbol does implement IMeta so that succeeds.
For understanding reader macros, it can be helpful to use "with-in- str" and "read" to capture exactly what read returns before eval gets hold of it:
user=> (def b (with-in-str "#^String a" (read))) #'user/b user=> (class b) clojure.lang.Symbol user=> b a user=> ^b {:tag String}Here, we def the var named user/b to be the value the reader returns when it reads "#^String a". We see that it's a Symbol whose name is a and whose metadata is {:tag String}.
In a normal read-eval-print operation (or for definitions, in a "read- compile-store" operation), the compiler can use the :tag information on the symbol a to produce better code to manipulate the value it represents in expressions.
--Steve
smime.p7s
Description: S/MIME cryptographic signature