SIMPLER VERSION:
This works:
user=> (map + [1 2 3] [4 5 6] [7 8 9])
(12 15 18)
This doesn't:
user=> (for [n (range 3)] [n (+ 1 n)])
([0 1] [1 2] [2 3])
user=> (map + (for [n (range 3)] [n (+ 1 n)]))
java.lang.ClassCastException
Why?
I am very new to clojure so this is probably a newbie mistake. In the code below I am trying to add multiple signals together. Each signal contains a vector (called data) and I want to do piece-wise addition. At the REPL, something like this:
user=> (map + [1 2 3] [4 5 6] [7 8 9])
(12 15 18)
My code looks like:
(defrecord signal [x y data])
(defrecord sampling [t0 dt n])
(defn random-signal [x y sampling tstart tend]
(let [t0 (:t0 sampling)
dt (:dt sampling)
n (:n sampling)
random-or-zero (fn [i]
(let [t (+ t0 (* dt i))]
(if (and (>= t tstart) (< t tend)) (- (* 2 (rand)) 1) 0)))
data (vec (for [i (range n)] (random-or-zero i)))]
(signal. x y data)))
(defn add-signals [signals]
(let [s0 (nth signals 0)]
(signal. (:x s0) (:y s0) (vec (map + (for [s signals] (:data s)))))))
(let [s (sampling. 0 0.1 10)
r1 (random-signal 5 6 s 0.3 0.5)
r2 (random-signal 5 6 s 0 1)]
(prn r1)
(prn r2)
(prn (add-signals [r1 r2])))
The random-signal code works fine, but the code fails in the "map +" with a class cast exception. So the (unhelpful) output is:
#:com.xxx.signal{:x 5, :y 6, :data [0 0 0 0.347104804641861 -0.043159177718418595 0 0 0 0 0]}
#:com.xxx.signal{:x 5, :y 6, :data [0.4956475276522727 -0.5843463943909746 -0.3375682325118188 0.5082971115650308 -0.971067613756232 0.6002887290735672 0.06900015064406251 -0.49986294956362287 0.657705242728329 0.7737992261031372]}
Exception in thread "main" java.lang.RuntimeException: java.lang.ClassCastException (fake.clj:0)
at clojure.lang.Compiler.eval(Compiler.java:5440)
at clojure.lang.Compiler.load(Compiler.java:5857)
at clojure.lang.Compiler.loadFile(Compiler.java:5820)
at clojure.main$load_script.invoke(main.clj:221)
at clojure.main$script_opt.invoke(main.clj:273)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:408)
at clojure.lang.Var.invoke(Var.java:365)
at clojure.lang.AFn.applyToHelper(AFn.java:161)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.RuntimeException: java.lang.ClassCastException
at clojure.lang.LazySeq.sval(LazySeq.java:47)
at clojure.lang.LazySeq.seq(LazySeq.java:56)
at clojure.lang.RT.seq(RT.java:450)
at clojure.lang.LazilyPersistentVector.create(LazilyPersistentVector.java:31)
at clojure.core$vec.invoke(core.clj:318)
at com.xxx.fake$add_signals.invoke(fake.clj:60)
at com.xxx.fake$eval223.invoke(fake.clj:74)
at clojure.lang.Compiler.eval(Compiler.java:5424)
... 15 more
Caused by: java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2990)
at clojure.core$cast.invoke(core.clj:293)
at clojure.core$_PLUS_.invoke(core.clj:815)
at clojure.core$map$fn__3699.invoke(core.clj:2094)
at clojure.lang.LazySeq.sval(LazySeq.java:42)
... 22 more
Process finished with exit code 1
What am I doing wrong?
If you pass an index equal to the count of the vector, Clojure will add the element as if you had used conj. However, if you pass an index that is negative or greater than the count, you'll get an IndexOutOfBoundsException: Since vectors are indexed, you can also get a reversed sequence of a vector's items using rseq:
Clojure provides basic set operations like union / difference / intersection, as well as some pseudo-relational algebra support for 'relations', which are simply sets of maps - select / index / rename / join.
Clojure provides full support for JVM primitive values by default, allowing high performance, idiomatic Clojure code for numeric applications. Clojure also supports the Java boxed number types derived from java.lang.Number, including BigInteger and BigDecimal, plus its own Ratio type. There is some special handling:
By default Clojure operates with natural numbers as instances of Java’s long primitive type. When a primitive integer operation results in a value that too large to be contained in a primitive value, a java.lang.ArithmeticException is thrown.
This won't work,
(map + (for [n (range 3)] [n (+ 1 n)]))
because now you are passing map, seq of seqs (one seq as opposed to 3 for your first example),
this is equal to,
(map + [[1 2 3] [4 5 6] [7 8 9]])
if you do,
(apply map + (for [n (range 3)] [n (+ 1 n)]))
it will evaluate to,
(map + [0 1] [1 2] [2 3])
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