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))
Related
I need to replace an integer with a string in clojure but only for 20% of the outputted integers.
(defn factor5 [x]
(if (= (mod x 3) (mod x 5) 0) "BuzzFizz"
(if (= (mod x 5) 0) "buzz"
(if (= (mod x 3) 0) "fizz" x))))
here i have a fizzbuzz program which prints out "fizz" if the number is a multiple of 3 or "buzz" if it is a multiple of 5 and "BuzzFizz" is printed if is a multiple of both. if an integer is neither of the above multiplies the integer gets printed. What i need is to print "Boom" instead of the integer but only for 20% of the integers.
some pseudo code
if(x == int){
print out Boom instead of x only for 20% }
else{
print out x}
I have very limited exprience in clojure as my pseudocode is java based
Please see the Clojure Cheatsheet for a comprehensive listing of functions.
The one you want is rand, and a test like:
(if (< (rand) 0.2) ....)
if you want the decision made randomly you could use one of the rand runctions in an if statement like so:
user> (defn x20% [x]
(if (rand-nth [true false false false false])
"Boom"
x))
#'user/x20%
user> (x20% 5)
5
user> (x20% 5)
5
user> (x20% 5)
"Boom"
user> (x20% 5)
5
there are also rand and rand-int. which you use is somewhat a matter of style and the specifics of your function:
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
true
user> (> 2 (rand-int 10))
false
user> (> 0.2 (rand))
true
user> (> 0.2 (rand))
(defn factor-5 [x]
(if (and (number? x) (zero? (rem x 1)))
(if (zero? (rand-int 5))
"Boom"
x)))
This returns the required value rather than printing it.
It tests that its argument is numeric, and - if so - that it is a
whole number value, which could be byte, short, int, ... .
(rand-int 5) chooses randomly from 0, 1, ... 4.
(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 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))
I could have sworn I had alength working previously, but I don't quite know what I am doing wrong right now:
user=> (alength '(1 2 3))
IllegalArgumentException No matching method found: alength clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79)
user=> (alength [1 2 3])
IllegalArgumentException No matching method found: alength clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:79)
user=> (doc alength)
-------------------------
clojure.core/alength
([array])
Returns the length of the Java array. Works on arrays of all
types.
nil
What should I be doing to get the length of a list/array in Clojure?
Try using count:
(count '(1 2 3))
=> 3
(count [1 2 3])
=> 3
As the docstring says, alength works on Java™ arrays, such as a String[] or Integer[], which is definitely an incompatible type with Clojure lists or vectors, for which you want to use count:
user=> (def x '(1 2 3))
#'user/x
user=> (def xa (to-array x))
#'user/xa
user=> (class x)
clojure.lang.PersistentList
user=> (class xa)
[Ljava.lang.Object;
user=> (alength xa)
3
user=> (alength x)
java.lang.IllegalArgumentException: No matching method found: alength (NO_SOURCE_FILE:0)
user=> (count x)
3
[Ljava.lang.Object; is the weird way toString is defined to output for native Object arrays.
It should be count.
user=> (count '(1 2 3))
3
This may be overkill, but you could imitate Common LISP's length function like this:
(def length
(fn [lst]
(loop [i lst cnt 0]
(cond (empty? i) cnt
:t (recur (rest i)(inc cnt))))))
You can do that using the recursive way:
(defn length
[list]
(if (empty? list) 0
(+ 1 (length (rest list)))))
Hope it helps!
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