have a hint here:
for whatever reason the first param in a function here is treated as integer. Adding type hint helps to solve this problem:
user> (reduce (fn [^long h c]
(unchecked-add (unchecked-multiply h 31) (long c)))
1125899906842597
"hello")
7096547112155234317
update:
moreover: it looks that it comes from the unchecked-multiply
user> (reduce (fn [h c]
(unchecked-add (unchecked-multiply ^long h 31) (long c)))
1125899906842597
"hello")
7096547112155234317
i will make some additional research, and update here, in case of any new information
update 2:
ok, that's what i've found out:
looking at the clojure's documentation at https://github.com/clojure/clojure/blob/master/src/jvm/clojure/lang/Numbers.java
we can see the following:
our case
static public Number unchecked_multiply(Object x, long y){return multiply(x,y);}
leads to:
static public Number multiply(Object x, long y){
return multiply(x,(Object)y);
}
then:
static public Number multiply(Object x, Object y){
return ops(x).combine(ops(y)).multiply((Number)x, (Number)y);
}
so at the end it calls multiply method from LongOps inner class.
final public Number multiply(Number x, Number y){
return num(Numbers.multiply(x.longValue(), y.longValue()));
}
so finally it leads us to a simple (checked?) multiply:
static public long multiply(long x, long y){
if (x == Long.MIN_VALUE && y < 0)
return throwIntOverflow();
long ret = x * y;
if (y != 0 && ret/y != x)
return throwIntOverflow();
return ret;
}
kaboom!
so i don't know whether it is a bug or the desired behavior, but it looks really weird to me.
so the only thing i could advice, is to always remember to typehint your values when using unchecked math in clojure.