Clojure:调用超类方法

Clojure : call a superclass method

我有一个很大的问题,我无法解决,我真的没有找到错误。

我想使用这个功能:

http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/optim/univariate/BrentOptimizer.html

Apache 的示例测试代码是:

(来源:https://github.com/apache/commons-math/blob/3.6-release/src/test/java/org/apache/commons/math3/optim/univariate/BrentOptimizerTest.java

public void testSinMin() {
    UnivariateFunction f = new Sin();
    UnivariateOptimizer optimizer = new BrentOptimizer(1e-10, 1e-14);
    Assert.assertEquals(3 * Math.PI / 2, optimizer.optimize(new MaxEval(200),
                                                            new UnivariateObjectiveFunction(f),
                                                            GoalType.MINIMIZE,
                                                            new SearchInterval(4, 5)).getPoint(), 1e-8);

所以我尝试用 Clojure 和另一个函数重现代码:

(defn atomic-apache-peak-value [x]
  (let [lamb ((x :parameters) 0)
        x0 ((x :parameters) 1)
        f (D2Sigmoid. lamb x0)
        optimizer (BrentOptimizer. 0.0001 0.0001)
        maxeval (MaxEval. 1000)
        of (UnivariateObjectiveFunction. f)
        goal (GoalType/MINIMIZE)
        interval (SearchInterval. x0 (* 2 x0))]
    (-> (.optimize optimizer maxeval of goal interval)
        (.getPoint))))

Clojure 告诉我 "No matching method found : optimize for class ....BrentOptimizer"

我尝试在 let 中逐行计算代码行并且它有效,所以问题是优化。

该方法是在超类上实现的,所以我导入了它们

[org.apache.commons.math3.optim.univariate UnivariateOptimizer BrentOptimizer UnivariateObjectiveFunction SearchInterval]
[org.apache.commons.math3.optim BaseOptimizer MaxEval]

它没有改变任何东西。

你认为我有语法问题或错误还是只是做错了方法?

谢谢

编辑:

忘了说

(.optimize optimizer)

version 从 Apache 抛出异常但被发现。所以我不认为 Clojure 找不到源代码。 可能语法有问题?

也试过Goaltype/MINIMIZE没有括号

编辑 2:

最终工作代码

(defn atomic-apache-peak-value [x]
  (let [lamb ((x :parameters) 0)
        x0 ((x :parameters) 1)
        f (D2Sigmoid. lamb x0)
        optimizer (BrentOptimizer. 0.0001 0.0001)
        maxeval (MaxEval. 1000)
        of (UnivariateObjectiveFunction. f)
        goal GoalType/MINIMIZE
        interval (SearchInterval. x0 (* 2 x0))]
    (-> (.optimize optimizer (into-array OptimizationData [maxeval of goal interval]))
        (.getPoint))))

好的,让我们创建一个正确的答案。从 Clojure 调用 Java 方法时,查找方法的实际签名很重要。仅从 Java 示例代码复制可能并不总是有效。这主要是由于 vargars。 Java Clojure 中的互操作需要程序员在涉及可变参数时做一些额外的工作。

您尝试调用的 optimize 方法的签名是:

public UnivariatePointValuePair optimize(OptimizationData... optData)
                              throws TooManyEvaluationsException

注意 ...,这意味着该方法采用 0 个或多个 OptimizationData 类型的参数。在Java中,只要foo、bar、baz的类实现了OptimizationData接口,就可以像optimize(foo, bar, baz)一样调用该方法。

然而,这种对可变参数的处理主要是由于 Java 编译器。在幕后,该方法实际上需要一个 OptimizationData [] 类型的参数 - OptimizationData 的数组。 Java 编译器生成的代码将参数打包成一个数组,程序员不用担心。

但是当从 Clojure 调用这些方法时,程序员必须创建数组。就好像该方法的签名在 Clojure 编译器中显示为 optimize(OptimizationData[] optData)

在 Clojure 中创建数组并不需要很多时间。一种方法是使用 into-array 函数。必要的点点滴滴如下:

(import '(org.apache.commons.math3.optim OptimizationData))

(.optimize  (into-array OptimizationData [optimizer maxeval of goal interval]))

另外,GoalType/MINIMIZE两边不需要括号。括号表示列表,列表在 Clojure 中作为函数调用求值。这里我们不需要调用 GoalType/MINIMIZE 函数,我们只需要那个值。