Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sum multiple vectors from some structs in Clojure

Tags:

clojure

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?

like image 808
andrew cooke Avatar asked Aug 12 '11 20:08

andrew cooke


People also ask

How do I add an element to a vector in Clojure?

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:

What are the basic set operations in CL Clojure?

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.

Does CL Clojure support primitive numbers?

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:

Why does Clojure throw ArithmeticException when using natural numbers?

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.


1 Answers

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])
like image 142
Hamza Yerlikaya Avatar answered Nov 29 '22 19:11

Hamza Yerlikaya