2016-03-22 67 views
2

我想將Java Apache Maths 3封裝到Clojure中,但是我遇到了一個我不明白的問題。Clojure和Java interop:返回void的函數

這裏是的Javadoc:

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

addValue增加了一個值的對象,但返回void的方法。我想象這個對象內有一些內部數據。

在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")))))) 

代碼不起作用(回報[楠楠],這樣就意味着價值尚未添加),證實當我嘗試(.getN REG) = 0 如果我單獨試一下,我的意思是第一

(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機制我缺少像對象不能更改函數內?由於

回答

2

mapzipmap是懶惰的,所以當你在do使用它們,不要問他們返回實際值或(使用doalldorun),這樣所有的元素都實現了,所有的副作用發生迫使他們(如調用.addData是一個副作用,改變某些狀態)傳遞到map的函數根本不會被調用。當您在REPL中使用這些函數時,結果打印將嘗試渲染map操作的結果,從而實現懶惰seq。

如果您不需要map的實際結果,但只是希望應用副作用,則可以使用doseq代替。

+0

非常感謝,看起來我錯過了很多關於Clojure的知識。我用doall解決了這個問題,因爲它不適合大量計算,但我會考慮在使用doseq之後! –

+2

你被「懶蟲」咬了,它只會在你不看的時候咬人;-) –