我不知道如何真正命名我的问题,因为我不知道如何开始考虑这个,所以我会说明问题。 想象一下,我有几个使用相同语法的Java对象静态方法,例如:
/**
* Floor function
*
* @param ndArray
* @return
*/
public static INDArray floor(INDArray ndArray, boolean dup) {
return exec(dup ? new Floor(ndArray.dup()) : new Floor(ndArray));
}
/**
* Signum function of this ndarray
*
* @param toSign
* @return
*/
public static INDArray sign(INDArray toSign, boolean dup) {
return exec(dup ? new Sign(toSign, toSign.dup()) : new Sign(toSign));
}
所以这是一个示例虚拟包装器:
(defn floor
^INDArray
[^INDArray a ^boolean dup]
(Transforms/floor a dup))
(defn sign
^INDArray
[^INDArray a ^boolean dup]
(Transforms/sign a dup))
这里的问题是你浪费时间编写具有相同模板的函数,这是第一次没问题......但是想象一下你想要在更改/破坏代码/性能调整/其他情况下更新所有这些函数。
我搜索了这个问题,却一无所获。理想的情况是(一个宏?),如:
(defoperator floor Transforms/floor)
或者
(def floor (->operator Transforms/floor))
我不知道是否可以为初学者调用“通用”静态方法,即使它是一个非常常见的用例并且没有找到任何答案。 我怀疑情况并非如此,因为在repl中键入“Transforms / floor”会将其视为静态字段而不是方法,但我不确定。
答案 0 :(得分:4)
您可以编写一个扩展为包含重复代码的函数定义的宏:
(defmacro defoperator [op]
`(defn ~op ; Create a function with "op" as the name
^INDArray
[^INDArray a#, dup#]
(. Transforms ~op a# dup#))) ; (. Transforms floor) is the same as (Transforms/floor)
现在调用(defoperator floor)
会发出一个类似于:
(defn floor
^INDArray
[^INDArray a, dup]
(. Transforms floor a dup))
此宏假定静态方法名称与要发出的函数相同。如果您希望它们有可能不同,可以使用备用版本:
(defmacro defoperator [fn-name static-name]
`(defn ~fn-name
^INDArray
[^INDArray a#, dup#]
(. Transforms ~static-name a# dup#)))
注意,我摆脱了你的^boolean
提示。您无法提示布尔基元。我不确定您使用的是哪种版本的Clojure,但这在1.8.0中无效。