Clojure和Java互操作:返回void的函数

Clojure and Java interop : functions that return void

我正在尝试将Java Apache Maths 3package到Clojure中,但是遇到一个我不明白的问题。

这是javadoc:

http://commons.apache.org/proper/commons-math/javadocs/api-3.3/index.html

方法addValue向对象添加一个值,但返回void。我想这个对象内部有一些内部数据。

在Java中,我会这样做:

1
regression.addValue(1,2);

我在Clojure中定义了将其package的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
;;----------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中单独使用它时,这些功能可以正常工作。

然后我定义了一个完整的package器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
(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"))))))

代码不起作用(返回[NaN NaN],因此表示尚未添加值),当我尝试(.getN reg)= 0时确认
如果我单独尝试,我的意思是首先

1
2
3
(def reg (simple-regression))
(add-points {:x [1 2 3] :y [0.1 0.2 0.3]} reg)
[(.getSlope reg) (.getIntercept reg)]

没问题,一切正常。

但是在函数内部,没有。我尝试了很多版本,其中一个带有

1
_ (add-points data reg)

我的印象是,在函数内部未添加点。如果我复制粘贴do

,则相同

我是否缺少一种更通用的Java机制,例如对象无法在函数内更改?谢谢


mapzipmap是惰性的,因此当您在do中使用它们时,不要要求它们返回实际值或强制它们(使用doalldorun),因此所有元素都是实现并发生所有副作用(例如,调用.addData是更改某些状态的副作用),根本不会调用传递到map的函数。在REPL中使用这些功能时,结果打印将尝试呈现map操作的结果,从而实现延迟序列。

如果您不需要map的实际结果,而只想应用副作用,则可以改用doseq