在clojure 1.5.1的lighttable下使用rxjava(http://netflix.github.io/RxJava/javadoc/),考虑以下内容(使用副作用,变异(恐怖!)外部收集器从monad中提取数据)
(ns expt1.core (:import [rx]))
(def ^:private collector (atom []))
(defn- collect [item]
(reset! collector (conj @collector item)))
(def string-explode (partial map identity))
(reset! collector [])
(->
(Observable/toObservable ["one" "two" "three"])
(.mapMany #(Observable/toObservable (string-explode %)))
(.subscribe collect)
)
@collector
产生:
[\o \n \e \t \w \o \t \h \r \e \e]
我想说
(reset! collector [])
(->
(Observable/toObservable ["one" "two" "three"])
(.mapMany (comp Observable/toObservable string-explode))
(.subscribe collect)
)
但是,惊喜
clojure.lang.Compiler$CompilerException: java.lang.RuntimeException: Unable to find static field: toObservable in class rx.Observable, compiling:(NO_SOURCE_PATH:93:1)
Compiler.java:6380 clojure.lang.Compiler.analyze
Compiler.java:6322 clojure.lang.Compiler.analyze
Compiler.java:3624 clojure.lang.Compiler$InvokeExpr.parse
Compiler.java:6562 clojure.lang.Compiler.analyzeSeq
...
事实上,只是
Observable/toObservable
产生类似的异常。为什么Clojure可以在类似
的表达式中找到Observable/toObservable
#(Observable/toObservable (string-explode %))
但不是像
这样的表达式(comp Observable/toObservable string-explode)
答案 0 :(得分:4)
Observable/toObservable
是一个Java方法,而不是Clojure函数。您不能将Java方法视为函数值,就像使用Clojure函数一样。 comp
组成Clojure函数(实现IFn
接口的对象)。解决方案:将方法调用包装在Clojure函数中。
另一件事:
(defn- collect [item]
(reset! collector (conj @collector item)))
应该是:
(defn- collect [item]
(swap! collector conj item)))
当您不想使用旧值时,仅在原子上使用reset!
。当你这样做时,使用swap!
,否则不保证原子更新(另一个线程可以在你读取它的值后更新原子)。