开发者

How to sum multiple vectors from some structs in Clojure

开发者 https://www.devze.com 2023-03-28 07:14 出处:网络
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)])

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.584346394390开发者_Python百科9746 -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?


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])
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号