【问题标题】:Clojure and Java interop : functions that return voidClojure 和 Java 互操作:返回 void 的函数
【发布时间】:2016-03-22 15:12:28
【问题描述】:

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

这里是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"))))))

代码不起作用(返回 [NaN NaN] 表示尚未添加值),当我尝试 (.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 机制,比如对象无法在函数内更改?谢谢

【问题讨论】:

    标签: clojure clojure-java-interop


    【解决方案1】:

    mapzipmap 是惰性的,因此当您在 do 中使用它们时,不要要求它们返回实际值或强制它们(使用 doalldorun),因此所有元素都已实现并且所有副作用都会发生(例如,调用.addData 是改变某些状态的副作用)您传递给map 的函数根本不会被调用。在REPL中使用这些函数时,结果打印会尝试渲染map操作的结果,从而实现lazy seq。

    如果您不需要来自 map 的实际结果,而只是希望应用副作用,则可能需要改用 doseq

    【讨论】:

    • 非常感谢,看来我缺少很多关于 Clojure 的知识。我用 doall 解决了这个问题,因为它不是用于大计算,但我会考虑在之后使用 doseq!
    • 你被“懒虫”咬了,它只会在你不注意的时候咬人;-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 1970-01-01
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多