Clojure 和 Java 互操作:return 无效的函数
Clojure and Java interop : functions that return void
我正在尝试将 Java Apache Maths 3 包装到 Clojure 中,但我遇到了一个我不明白的问题。
这是 javadoc :
http://commons.apache.org/proper/commons-math/javadocs/api-3.3/index.html
方法 addValue
向对象添加了一个值,但 returns 无效。我想这个对象里面有一些内部数据。
在Java,我会做:
regression.addValue(1,2);
我在 Clojure 中定义了函数来包装它:
;;----------Simple regression object builder----------
(defn simple-regression []
(SimpleRegression.))
;;----------Add points----------
(defn add-point
([reg [x y]]
(.addData reg (double x) (double y)))
([reg x y]
(.addData reg (double x) (double y))))
(defn add-points
([data reg]
(let [x (data :x)
y (data :y)
d (zipmap x y)]
(map (fn [[k v]] (add-point reg k v)) d)))
([x y reg]
(let [d (zipmap x y)]
(map (fn [[k v]] (add-point reg k v)) d))))
当我在 repl 中单独使用这些函数时,这些函数工作正常。
然后我定义了一个完整的包装器:
(defn lin-reg
([data & {:keys [type] :or {type "simple"}}]
(let [reg (simple-regression)]
(do (add-points data reg)
(cond (= type "simple")
[(.getSlope reg) (.getIntercept reg)]
(= type "extended")
{:params [(.getSlope reg) (.getIntercept reg)] :r (.getR reg) :r2 (.getRSquare reg) :significance (.getSignificance reg)}
(= type "full")
{:params [(.getSlope reg) (.getIntercept reg)] :r (.getR reg) :r2 (.getRSquare reg) :significance (.getSignificance reg)
:conf-intervals [(.getSlopeConfidenceInterval reg) (.getInterceptConfidenceInterval reg)] :params-sse [(.getSlopeStdErr reg) (.getInterceptStdErr reg)]
:sse (.getSumSquaredErrors reg) :ssto (.getTotalSumSquares reg) :ssm (.getRegressionSumSquares reg) :cross-products-sum (.getSumOfCrossProducts reg)}
:else
(println "regression type can only be : simple, extended or full"))))))
代码不起作用(returns [NaN NaN] 所以这意味着没有添加值),当我尝试 (.getN reg) = 0 时确认
如果我单独尝试,我的意思是 first
(def reg (simple-regression))
(add-points {:x [1 2 3] :y [0.1 0.2 0.3]} reg)
[(.getSlope reg) (.getIntercept reg)]
没问题,一切正常。
但是在函数内部,没有。我尝试了很多版本,其中一个带有
_ (add-points data reg)
我的印象是函数内部没有添加点。如果我复制粘贴 do
.
是一样的
是否有更通用的 Java 机制我缺少这样的对象不能在函数内部更改?谢谢
map
和 zipmap
是懒惰的,所以当你在 do
中使用它们时,不要要求它们 return 实际值或强制它们(使用 doall
或 dorun
) 所以所有的元素都实现了并且所有的副作用都发生了(例如调用 .addData
是改变某些状态的副作用)你传递给 map
的函数不会被调用。当你在 REPL 中使用这些函数时,结果打印将尝试渲染 map
操作的结果,从而实现惰性 seq.
如果您不需要 map
的实际结果,而只想应用副作用,则可能需要使用 doseq
。
我正在尝试将 Java Apache Maths 3 包装到 Clojure 中,但我遇到了一个我不明白的问题。
这是 javadoc :
http://commons.apache.org/proper/commons-math/javadocs/api-3.3/index.html
方法 addValue
向对象添加了一个值,但 returns 无效。我想这个对象里面有一些内部数据。
在Java,我会做:
regression.addValue(1,2);
我在 Clojure 中定义了函数来包装它:
;;----------Simple regression object builder----------
(defn simple-regression []
(SimpleRegression.))
;;----------Add points----------
(defn add-point
([reg [x y]]
(.addData reg (double x) (double y)))
([reg x y]
(.addData reg (double x) (double y))))
(defn add-points
([data reg]
(let [x (data :x)
y (data :y)
d (zipmap x y)]
(map (fn [[k v]] (add-point reg k v)) d)))
([x y reg]
(let [d (zipmap x y)]
(map (fn [[k v]] (add-point reg k v)) d))))
当我在 repl 中单独使用这些函数时,这些函数工作正常。
然后我定义了一个完整的包装器:
(defn lin-reg
([data & {:keys [type] :or {type "simple"}}]
(let [reg (simple-regression)]
(do (add-points data reg)
(cond (= type "simple")
[(.getSlope reg) (.getIntercept reg)]
(= type "extended")
{:params [(.getSlope reg) (.getIntercept reg)] :r (.getR reg) :r2 (.getRSquare reg) :significance (.getSignificance reg)}
(= type "full")
{:params [(.getSlope reg) (.getIntercept reg)] :r (.getR reg) :r2 (.getRSquare reg) :significance (.getSignificance reg)
:conf-intervals [(.getSlopeConfidenceInterval reg) (.getInterceptConfidenceInterval reg)] :params-sse [(.getSlopeStdErr reg) (.getInterceptStdErr reg)]
:sse (.getSumSquaredErrors reg) :ssto (.getTotalSumSquares reg) :ssm (.getRegressionSumSquares reg) :cross-products-sum (.getSumOfCrossProducts reg)}
:else
(println "regression type can only be : simple, extended or full"))))))
代码不起作用(returns [NaN NaN] 所以这意味着没有添加值),当我尝试 (.getN reg) = 0 时确认 如果我单独尝试,我的意思是 first
(def reg (simple-regression))
(add-points {:x [1 2 3] :y [0.1 0.2 0.3]} reg)
[(.getSlope reg) (.getIntercept reg)]
没问题,一切正常。
但是在函数内部,没有。我尝试了很多版本,其中一个带有
_ (add-points data reg)
我的印象是函数内部没有添加点。如果我复制粘贴 do
.
是否有更通用的 Java 机制我缺少这样的对象不能在函数内部更改?谢谢
map
和 zipmap
是懒惰的,所以当你在 do
中使用它们时,不要要求它们 return 实际值或强制它们(使用 doall
或 dorun
) 所以所有的元素都实现了并且所有的副作用都发生了(例如调用 .addData
是改变某些状态的副作用)你传递给 map
的函数不会被调用。当你在 REPL 中使用这些函数时,结果打印将尝试渲染 map
操作的结果,从而实现惰性 seq.
如果您不需要 map
的实际结果,而只想应用副作用,则可能需要使用 doseq
。