Why does (int 10) produce a Long instance?
Asked Answered
W

2

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
Wildawildcat answered 26/2, 2012 at 21:54 Comment(1)
It was fixed in Clojure 1.5: dev.clojure.org/jira/browse/CLJ-820 I tested it in Clojure 1.6 and (type (int 10)) gives java.lang.Integer.Gigahertz
F
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.

Fan answered 26/2, 2012 at 22:21 Comment(0)
S
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
Stratification answered 26/2, 2012 at 22:15 Comment(7)
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?Wildawildcat
.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.Pazia
@DaveRay According to 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.Wildawildcat
@spoon16 As I said: "primitive integer".Stratification
>= 1.3 is incorrect: this confusing behavior is reverted in 1.4Verwoerd
@amalloy, What is the behavior in 1.4? does (int) produce an Integer?Wildawildcat
@spoon16 Yes, it does. But don't take my word for it: try it out!Verwoerd

© 2022 - 2024 — McMap. All rights reserved.