13

Why does (int 10) not produce an instance of type java.lang.Integer?

; why Long here?
=> (type (int 10))
; java.lang.Long

; this one is also Long, why not java.lang.Number?
=> (type (num 10))
; java.lang.Long

=> (type (double 10))
; java.lang.Double
=> (type (long 10))
; java.lang.Long
=> (type (float 10))
; java.lang.Float
=> (type (short 10))
; java.lang.Short
=> (type (bigint 10))
; clojure.lang.BigInt
=> (type (bigdec 10))
; java.math.BigDecimal
=> (type (boolean 10))
; java.lang.Boolean
=> (type (char 10))
; java.lang.Character
=> (type (byte 10))
; java.lang.Byte
Eric Schoonover
  • 47,184
  • 49
  • 157
  • 202
  • It was fixed in Clojure 1.5: http://dev.clojure.org/jira/browse/CLJ-820 I tested it in Clojure 1.6 and (type (int 10)) gives java.lang.Integer. – Grzegorz Luczywo Jul 02 '14 at 08:55

2 Answers2

17

Clojure deals only with long integers internally. (int) is used to cast a long to an int for calling Java methods that expect an int argument.

In this case (int 10) does indeed return a Java int, but Clojure then promotes the int back to a long. (type) uses (class) to find out the type of its argument (in this case), and therefore the long gets boxed into a java.lang.Long.

You can produce java.lang.Integer by using one of the java.lang.Integer constructors or factory methods:

user> (type (Integer. 10))
java.lang.Integer

user> (type (Integer/valueOf 10))
java.lang.Integer

user> (type (Integer/decode "10"))
java.lang.Integer

...

(num) will upcast its argument to the abstract class java.lang.Number, but (type) will return the actual type of its argument, i.e. java.lang.Long again.

liwp
  • 6,746
  • 1
  • 27
  • 39
7

int is a cast to primitive integer for interop calls. Since each of type calls takes an Object things get boxed again and Clojure (>= 1.3) boxes to Long and Double. If you need an Integer you have to create one.

user=> (type (Integer/valueOf 10))
java.lang.Integer
kotarak
  • 17,099
  • 2
  • 49
  • 39
  • So why does `(.compareTo (Integer. 10) (int 10))` result in `ClassCastException java.lang.Long cannot be cast to java.lang.Integer`? Is this not an example of Java interop? – Eric Schoonover Feb 26 '12 at 23:46
  • `.compareTo` takes `Object`, so the result of `(int 10)` is immediately boxed back to a `Long` resulting in the exception inside `compareTo` when it tries to cast to `Integer`. It's a nice interaction between Clojure's boxing and the fact that generics like `java.lang.Comparable` in Java aren't reified. – Dave Ray Feb 27 '12 at 01:26
  • @DaveRay According to http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html `compareTo` takes an `Integer`, which does derive from `Object`. Is it correct to say that `(int)` should only be used when an `int` instance is required, it does not work for when an `Integer` instance is needed. – Eric Schoonover Feb 27 '12 at 04:11
  • @spoon16 As I said: "primitive integer". – kotarak Feb 27 '12 at 07:22
  • 3
    >= 1.3 is incorrect: this confusing behavior is reverted in 1.4 – amalloy Feb 27 '12 at 17:38
  • 1
    @amalloy, What is the behavior in 1.4? does (int) produce an Integer? – Eric Schoonover Feb 27 '12 at 22:27
  • 1
    @spoon16 Yes, it does. But don't take my word for it: try it out! – amalloy Feb 28 '12 at 04:13