Right.
> If you want to type hint something to primitive long you'd use #^long.
> For object long, use #^Long. Be warned that I'm still new at this, so
> I could be wrong.
Thanks for giving it a shot, but that's not quite right.
There's no way to use the hinting syntax (that is, the :tag
metadata) to indicate something is a primitive. Hinting
itself implies an Object of some class.
However Clojure can work with primitives -- the one place
where a primitive can be stored is in a local (not an
argument, not a parameter, not a return value).
(defn foo [x]
(let [y (int x)]
...))
There x is a parameter, and therefore refers to some kind of
Object. But the local y is bound to (int x), which the
compiler can see is always a primitive int, therefore it
will make y a primitive int.
It can be hard to distinguish between a primitive local and
an Object local -- Clojure does what it can to treat them
similarly. But there are a few clues, for example trying to
type hint (which implies Object) a primitive (which cannot
be an Object) is clearly wrong:
(let [x (int 5)]
(.shortValue #^Integer x)) ; not right
java.lang.UnsupportedOperationException: Can't type hint a primitive
local (NO_SOURCE_FILE:70)
Of course if x were not a primitive, it'd be quite alright:
(let [x 5]
(.shortValue #^Integer x)) ; fine
There's little thing in contrib to help you see what the
Clojure compiler knows about a particular expression:
(use '[clojure.contrib.repl-utils :only [expression-info]])
(expression-info '(let [x 5] x))
==> {:class java.lang.Integer, :primitive? false}
(expression-info '(let [x 5] (.shortValue #^Integer x)))
==> {:class short, :primitive? true}
(expression-info '(let [x 5] x))
==> {:class java.lang.Integer, :primitive? false}
Hope that helps,
--Chouser