I'm trying to use BigDecimals in Clojure to model (if necessary) arbitrary precision numbers.
I have a strange error when I try to instantiate a BigDecimal from an unscaled value and scale factor:
user=> 1.31M
1.31M (OK)
user=> (class 1.31M)
java.math.BigDecimal (OK)
user=> (.unscaledValue 1.31M)
131 (OK)
user=> (.scale 1.31M)
2 (OK)
user=> (.movePointLeft (BigDecimal. 131) 2)
1.31M (OK)
user=> (BigDecimal. (BigInteger. "131") 2)
1.31M
user=> (BigDecimal. 131N 2) (WRONG!!!)
IllegalArgumentException No matching ctor found for class java.math.BigDecimal clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
user=> (BigDecimal. (BigInteger. "131") 2)
1.31M
The problem here is that the clojure big integer IS NOT a java.math.BigInteger object. Even (bigint x) doesn't work:
user=> (doc bigint)
-------------------------
clojure.core/bigint
([x])
Coerce to BigInt
nil
And by the way BigInteger constructor doesn't directly accept numeric values. I know I could also do something like:
user=> (BigDecimal. (BigInteger. (.toByteArray (.unscaledValue 1.31M))) (.scale 1.31M))
1.31M
My question is: is there a more idiomatic way of directly manage BigInteger objects from Clojure? Or am I stuck to wrap everything in a custom library, like:
user=> (defn my-bigint [x] (BigInteger. (.toString x)))
#'user/my-bigint
user=> (my-bigint 131)
131
user=> (BigDecimal. (my-bigint 131) 2)
1.31M
Thanks in advance for the help!
UPDATE: I NEED a BigInteger for serialization purposes: my idea is to store a BigDecimal as a byte array and an integer. My problem is that in Clojure, if I want, I cannot pass the result of .unscaledValue back and forth 'cause Clojure doesn't handle BigInteger created from Integers (neither do Java, for what it matters):
user=> (BigInteger. 3)
IllegalArgumentException No matching ctor found for class java.math.BigInteger clojure.lang.Reflector.invokeConstructor (Reflector.java:183)
A call to .toString on the number is unuseful for the semantics of serialization (and more error prone). I would like to know if in Clojure there is an idiomatic way to write something like:
user=> (bigdec 131N 2)
No .movePointLeft (creation of two different objects without benefits), no .toString (I have a number, I stringify it and then create a BigInteger, another number, from it?), no slow and indirect method: just plain BigInteger and scale value.
Vinz
=> (type (.unscaledValue 1.31M))
java.math.BigInteger
=> (type (biginteger 131))
java.math.BigInteger
=> (BigDecimal. (biginteger 131) 2)
1.31M
user=> (.movePointLeft (bigdec 131) 2)
1.31M
user=> (.movePointLeft (bigdec 131N) 2)
1.31M
user=> (source bigdec)
(defn bigdec
"Coerce to BigDecimal"
{:tag BigDecimal
:added "1.0"
:static true}
[x] (cond
(decimal? x) x
(float? x) (. BigDecimal valueOf (double x))
(ratio? x) (/ (BigDecimal. (.numerator x)) (.denominator x))
(instance? BigInteger x) (BigDecimal. ^BigInteger x)
(number? x) (BigDecimal/valueOf (long x))
:else (BigDecimal. x)))
I like this a bit better:
(-> 131M (.movePointLeft 2))
Related
(class (range 10))
;=> clojure.lang.LazySeq
(class (seq (range 10))
;=> clojure.lang.ChunkedCons
From my understanding, LazySeq is already an sequence, since:
(seq? (range 10))
;=> true
I guess I have an answer.
That's because using seq enforces the evaluation of the first element of LazySeq. Because seq returns nil when the collection & sequence is empty, it has to eval the element to decide that.
That's the exactly reason why rest is lazier than next, because (next s) is just (seq (rest s)).
To expand upon your answer (and because comments don't support new lines):
user=> (def r (range 10))
#'user/r
user=> (realized? r)
false
user=> (class r)
clojure.lang.LazySeq
user=> (def r2 (rest r))
#'user/r2
user=> (realized? r2)
ClassCastException clojure.lang.ChunkedCons cannot be cast to clojure.lang.IPending clojure.core/realized? (core.clj:6607)
user=> (class r2)
clojure.lang.ChunkedCons
user=> (realized? r)
true
I'm running Clojure 1.4.0. Why is it if I add Integer/MAX_VALUE and 1, I get a Long, but if I add Integer/MAX_VALUE to itself, I get an exception?
=> (def one 1)
=> (class one)
java.lang.Integer
=> (def max-plus-one (+ Integer/MAX_VALUE one))
=> max-plus-one
2147483648
=> (class max-plus-one)
java.lang.Long
=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:0)
Shouldn't they both act the same way? Why does adding two MAX_VALUE values overflows but adding 1 doesn't?
I've seen this SO question but they are getting different behaviour than I am.
That's strange, I see different results with Clojure 1.4.0and Java(TM) SE Runtime Environment (build 1.7.0_06-b24), on Ubuntu 12.04 64bit:
user=> *clojure-version*
{:major 1, :minor 4, :incremental 0, :qualifier nil}
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
4294967294
user=> (type 1)
java.lang.Long
user=> (def max-plus-one (+ Integer/MAX_VALUE one))
#'user/max-plus-one
user=> max-plus-one
2147483648
user=> (type max-plus-one)
java.lang.Long
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
4294967294
You can always check the Java classes which clojure.core uses for numerics, to see how the functionality is implemented:
The implementation of the + operator in:
(defn +
"Returns the sum of nums. (+) returns 0. Does not auto-promote
longs, will throw on overflow. See also: +'"
{:inline (nary-inline 'add 'unchecked_add)
:inline-arities >1?
:added "1.2"}
([] 0)
([x] (cast Number x))
([x y] (. clojure.lang.Numbers (add x y)))
([x y & more]
(reduce1 + (+ x y) more)))
Java implementation of adding longs:
final public Number add(Number x, Number y){
return num(Numbers.add(x.longValue(),y.longValue()));
}
Edits: Tested with Clojure 1.2.1
I have done a quick test with Clojure 1.2.1, and with that version of Clojure I get exactly your behavior.
user=> *clojure-version*
{:major 1, :minor 2, :incremental 1, :qualifier ""}
user=> (def one 1)
#'user/one
user=> (class 1)
java.lang.Integer
user=> (def max-plus-one (+ Integer/MAX_VALUE one))
#'user/max-plus-one
user=> max-plus-one
2147483648
user=> (class max-plus-one)
java.lang.Long
user=> (+ Integer/MAX_VALUE Integer/MAX_VALUE)
java.lang.ArithmeticException: integer overflow (NO_SOURCE_FILE:0)
I'd say that you did the test with Clojure 1.2.x, and not with 1.4.0. What is the value of *clojure-version* in your REPL?
Looks like you have your answer, but here are a few other interesting points:
java (all versions) and clojure's (>1.3.0) default behaviour differ in their behaviour wrt overflow
in java
(Long.MAX_VALUE + 1) == Long.MIN_VALUE
(Integer.MAX_VALUE + 1) == Integer.MIN_VALUE
// cast required to avoid promoting to int
(Byte.MAX_VALUE + (byte)1) == Byte.MIN_VALUE
This is because arithmetic wraps by default on the jvm
in clojure (>1.3.0)
(inc Long.MAX_VALUE)
=> ArithmeticOverflow
(inc Integer/MAX_VALUE)
=> a long with value Integer/MAX_VALUE + 1
(int (inc Integer/MAX_VALUE))
=> IllegalArgumentException Value
out of range for int: 2147483648
clojure does have versions of some ops that behave like java
(unchecked-inc Long.MAX_VALUE) => Long.MIN_VALUE
You can make the unchecked operations the default by setting *unchecked-math* to true
(set! *unchecked-math* true)
(inc Long/MAX_VALUE)
=> (Long.MIN_VALUE)
(int (inc Integer/MAX_VALUE))
=> (Integer.MIN_VALUE) of type Integer
There are lots of other interesting (unchecked-*) operations.
As of version 1.3.0 Clojure uses Longs for all primitive numbers. you just need to use larger numbers to get the overflow.
(def max-plus-one (+ Long/MAX_VALUE one))
I have two somewhat related problems, shown by the following:
user=> (if (symbol? 5) (meta (var 5)) 5)
CompilerException java.lang.ClassCastException: java.lang.Long cannot be cast to clojure.lang.Symbol, compiling:(NO_SOURCE_PATH:6)
user=> (defn dometa [x] (if (symbol? x) (meta (var x)) x))
CompilerException java.lang.RuntimeException: Unable to resolve var: x in this context, compiling:(NO_SOURCE_PATH:7)
user=>
In the first case, since 5 is not a symbol I would not expect (meta (var 5)) to be evaluated, but it is (or at least that's the way it seems to me).
In the second case, if I want to place the first expression in a function, and parameterize the value being tested, the (var ...) function no longer works.
The Var object is looked up at compile time. For the behaviour I'm inferring from your examples, you should use find-var.
user=> (if (symbol? 5) (meta (find-var 5)) 5)
5
user=> (defn dometa [x] (if (symbol? x) (meta (find-var x)) x))
#'user/dometa
I am trying to delay various calculations. I have functions of the following form,
(defn a-fn [a b]
(let [a (if (fn? a)
a
#(identity a))
b (if (fn? b)
b
#(identity b))]
(+ (a) (b))))
this allows me to pass a-fn, a value or a function that returns the value,
(a-fn 1 2)
(defn x [] 1)
(defn y [] 2)
(a-fn x y)
(a-fn x 2)
what I do is build a list of functions (like the one above) to operate on some data, fns may use other fns to retrieve their arguments or in some cases things don't change and they are assigned values as arguments. I was wondering is there a better way to achive this kind of behavior?
You can use delay and force:
user=> (defn a-fn [a b] (+ (force a) (force b)))
#'user/a-fn
user=> (a-fn 1 2)
3
user=> (def x (delay 1))
#'user/x
user=> (def y (delay 2))
#'user/y
user=> (a-fn x y)
3
user=> (a-fn x 2)
3
If you try something like (delay (prn :hello) 1) to test when the computation is done, note that printing the Delay object forces it; so (def x (delay ...)) is safe, but typing a plain (delay ...) in the REPL prompt is not.
There might be a more elegant way to do what you want, but here's at least a more generic version of it:
(defn delayed [reducer & fs]
(apply reducer (for [f fs] (if (fn? f) (f) f))))
(def a-fn (partial delayed +))
So delayed takes an arbitrary function and a list of function/values. If expands all the args and then applies the function to them. Then we use partial to define your a-fn using +:
user=> (a-fn 1 2)
3
user=> (a-fn (constantly 1) 2)
3
user=> (a-fn (constantly 1) 2 4)
7
Alternatively, it might make sense for delayed to return a function rather than using partial. Note sure which is better.
A better name than "delayed" is welcome :)
At the home site of Clojure, there is the following statement:
Strings, numbers, characters, true,
false, nil and keywords evaluate to
themselves.
Is there a single combined predicate that tests for any of these, combining string?, number?, char?, true?, false?, nil?, and keyword?. Should I just use (complement symbol?)?
Maybe I'm missing something, but you could use the following to test for any of those conditions and return true if one is true:
(defn self-eval?
[x]
(or (string? x)
(number? x)
(char? x)
(keyword? x)
(true? x)
(false? x)
(nil? x)))
It's easy enough to write a macro that asks "does the given expression evaluate to itself". In fact this is a good example of tasks that can only be done with a macro because they need to see the argument both evaluated and unevaluated.
(defmacro selfp [a] `(= ~a (quote ~a)))
#'user/selfp
user> (selfp 1)
true
user> (selfp +)
false
user> (selfp [1 2])
true
user> (selfp '(+ 1 2 3))
false
While strings, numbers, characters, keywords, and the booleans are all self-evaluating, other things such as [1 2] are as well,so this may not be a useful test in general.
Another option is to create a function that uses a map:
(defn myclassifier? [x]
(let [types-I-care-about #{java.lang.Sring ...}]
(if (types-I-care-about (type x))
true
false)))
Another option which may have better performance is to use java's dynamism:
(extend-type Object
IMyClassifier
(myclassifier? [x]
(let [c (.getClass x)]
(if (types-I-care-about (type c))
(do
(extend-type (.getClass x)
IMyClassifier
(myclassifier? [x] true))
true)
false))))
where types-I-care-about is a set of types you care about.