Type hints on primities

160 views
Skip to first unread message

BerlinBrown

unread,
Jun 19, 2009, 10:55:40 AM6/19/09
to Clojure
What are the type hints on primitives.
For example,

long abc = 3

is the type hint

#^long

or

#^Long

I also saw use of the java assembly? syntax before:

#^[[L?

or neither.

tmountain

unread,
Jun 19, 2009, 11:40:04 AM6/19/09
to Clojure
Taken from http://en.wikibooks.org/wiki/Learning_Clojure:

Java includes wrapper reference types for its primitive number types,
e.g. java.lang.Integer "boxes" (wraps) the primitive int type. Because
every Clojure function is a JVM method expecting Object arguments,
Java primitives are usually boxed in Clojure functions: when Clojure
calls a Java method, a returned primitive is automatically wrapped,
and any arguments to a Java method are automatically unwrapped as
necessary. (However, type hinting allows non-parameter locals in
Clojure functions to be unboxed primitives, which can be useful when
you're trying to optimize a loop.)

It looks like Clojure auto-boxes from long to Long by default:

user=> (type (long 3))
java.lang.Long

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.

Travis

Chouser

unread,
Jun 19, 2009, 12:15:26 PM6/19/09
to clo...@googlegroups.com
On Fri, Jun 19, 2009 at 11:40 AM, tmountain<TinyMo...@gmail.com> wrote:
>
> It looks like Clojure auto-boxes from long to Long by default:
>
> user=> (type (long 3))
> java.lang.Long

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

tmountain

unread,
Jun 19, 2009, 12:33:09 PM6/19/09
to Clojure
I had a feeling I might have been wrong on the primitive hint part.
Your explanation makes a lot of sense. Thanks for the clear
explanation.

Travis

On Jun 19, 12:15 pm, Chouser <chou...@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages