I've noticed that if I def
an int array and set an element in the array with a Long, then there are no complaints. However if I bind the int array in a let
block set an element with a Long, then an IllegalArgument exception is thrown. Could someone help me understand why this is?
The code below demonstrates the discrepancy. I tried it in both Clojure 1.8 and the latest beta version of 1.9 and got these results.
(def a (int-array 10))
(aset a 0 Long/MAX_VALUE) ;; sets first element to -1
(let [b (int-array 10)]
(aset b 0 Long/MAX_VALUE)) ;; throws java.lang.IllegalArgumentException: Value out of range for int:
This discrepancy is caused because type inference is occurring in the let
, but not in the def
. You can verify this by using type hints to switch the situation around:
(def ^"[I" a (int-array 10))
(aset a 0 Long/MAX_VALUE)
;; throws java.lang.IllegalArgumentException: Value out of range for int:
(let [^Object b (int-array 10)]
(aset b 0 Long/MAX_VALUE))
;; sets first element to -1
Or, alternatively:
(def a (int-array 10))
(aset ^"[I" a 0 Long/MAX_VALUE)
;; throws java.lang.IllegalArgumentException: Value out of range for int:
(let [b (int-array 10)]
(aset ^Object b 0 Long/MAX_VALUE))
;; sets first element to -1
This is because Clojure inlines calls to aset
when possible, which includes all these cases, but the inlined static method call has many overloads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With