2

我一直在玩clojure,并一直在用它来构建一个简单的小音频播放器。奇怪的是,有时,也许二十分之一,在联系服务器时,我会收到以下错误:

2010-04-20 15:33:20.963::WARN:  Error for /control
java.lang.StackOverflowError
    at clojure.lang.RT.seq(RT.java:440)
    at clojure.core$seq__4245.invoke(core.clj:105)
    at clojure.core$filter__5084$fn__5086.invoke(core.clj:1794)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:440)
    at clojure.core$seq__4245.invoke(core.clj:105)
    at clojure.core$filter__5084$fn__5086.invoke(core.clj:1794)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:440)
    at clojure.core$seq__4245.invoke(core.clj:105)
    at clojure.core$filter__5084$fn__5086.invoke(core.clj:1794)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:440)
    at clojure.core$seq__4245.invoke(core.clj:105)
    at clojure.core$filter__5084$fn__5086.invoke(core.clj:1794)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:440)
        ...

如果我再次这样做,它总是有效的。所以它似乎与时间或其他东西有关。有问题的代码是:

(defn add-track [t]
  (common/ref-add tracks t))

(defn add-collection [coll]
  (doseq [track coll] (add-track track)))

(defn ref-add [ref value]
  (dosync (ref-set ref (conj @ref value))))

其中 coll 是从此函数中提取的:

(defn tracks-by-album [album]
  (sort sort-tracks (filter #(= (:album %) album) @tracks)))

它使用:

(defn get-album-from-track [track]
  (seq/find-first #(= (:album track) (:name %)) @albums))

(defn sort-tracks [track1 track2]
  (cond (= (:album track1) (:album track2))
    (cond (and (:album-track track1) (:album-track track2))
      (< (:album-track track1) (:album-track track2))
      :else 0)
    :else
     (> (:year (get-album-from-track track1)) (:year (get-album-from-track track2)))))

它或多或少直接从我收到的请求中调用:

(when-handle-command cmd params (audio/tracks-by-album decoded-name))

(defn when-handle-command [cmd params data]
  (println (str "handling command:" cmd))
    ....)

我从来没有在我的日志中得到处理命令,所以当它按专辑播放时它必须死掉。

所以它似乎是堆栈跟踪中的曲目逐专辑功能。我只是不明白为什么它有时有效,有时无效。我说它是逐专辑曲目,因为它是唯一过滤的函数(包括它的子函数),正如在跟踪中看到的那样。

所有源代码均可在以下网址获得:http ://code.google.com/p/mucomp/ 。这是我学习 clojure 的小爱好项目,到目前为止它还是有很多 bug(这只是一个 bug :))所以我还没有真正喜欢告诉太多人这件事 :)

4

1 回答 1

1

我在 clojure 邮件列表上问了这个问题。看起来答案是过滤器返回一个惰性序列,当你链接它们时,你会在某个时候以堆栈溢出结束。可以使用 doall 强制生成序列。

于 2010-05-03T19:25:26.677 回答