Clojure +, +', and unchecked-add

+
In Clojure core there’s a handy function, +. I’ll bet you know what it does:
(+ 1 2 3)
;;=> 6
Let’s introduce a handy function as we explore:
(defn value-and-type
[& args]
(map (juxt identity type) args))
Let’s look at the largest supported Long:
(value-and-type Long/MAX_VALUE)
;;=> ([9223372036854775807 java.lang.Long])
What happens if we exceed it?
(value-and-type (+ 1 Long/MAX_VALUE))
;;=> Execution error (ArithmeticException) at java.lang.Math/addExact (Math.java:931).
;; long overflow
It throws!
+'
The fact that + throws on overflow is why +' exists:
(value-and-type (+' 1 Long/MAX_VALUE))
;;=> ([9223372036854775808N
;; clojure.lang.BigInt])
Instead of overflowing, it promoted from a Long to a BigInt. In addition to +', there are -', *', inc', and dec'.
unchecked-add
Now for unchecked-add. Notice how it wraps around:
(value-and-type
Long/MIN_VALUE
(unchecked-add Long/MAX_VALUE 1))
;;=> ([-9223372036854775808 java.lang.Long]
;; [-9223372036854775808 java.lang.Long])
In addition to unchecked-add, there are unchecked-subtract, unchecked-multiply, unchecked-inc, unchecked-dec, and unchecked-negate.
Summary
If you’re dealing with a Long, on overflow:
+throws+'promotes toBigIntunchecked-addwraps around
(+ Long/MAX_VALUE 1)
;;=> Execution error (ArithmeticException) at java.lang.Math/addExact (Math.java:931).
;; long overflow
(+' Long/MAX_VALUE 1)
;;=> 9223372036854775808N
(unchecked-add Long/MAX_VALUE 1)
;;=> -9223372036854775808



