将Java代码转换为快速Clojure代码
这个Java代码可以被翻译成同样快或几乎同样快的Clojure代码吗 我已经能够获得更简单的函数,比如添加两个数组,以合理的速度运行类型提示,但我无法让Clojure在合理的时间内使用Java互操作或白炽矩阵,使用函数或命令式样式来完成下面的函数 我是否遗漏了一些关于类型暗示的内容,还是最好用Java来做这种事情将Java代码转换为快速Clojure代码,clojure,Clojure,这个Java代码可以被翻译成同样快或几乎同样快的Clojure代码吗 我已经能够获得更简单的函数,比如添加两个数组,以合理的速度运行类型提示,但我无法让Clojure在合理的时间内使用Java互操作或白炽矩阵,使用函数或命令式样式来完成下面的函数 我是否遗漏了一些关于类型暗示的内容,还是最好用Java来做这种事情 static double[][] grad2_stencil= { {0,0,-1,0,0}, {0,0,16,0,0},
static double[][] grad2_stencil= { {0,0,-1,0,0},
{0,0,16,0,0},
{-1,16,-60,16,-1},
{0,0,16,0,0},
{0,0,-1,0,0} };
public static double grad2(double[][] array, int x, int y){
double temp=0;
int L=array.length;
for(int i=0; i<5; i++){
for(int j=0; j<5; j++){
temp+=array[((x+i-2)%L+L)%L][((y+j-2)%L+L)%L]*grad2_stencil[i][j];
}
}
return temp/12.0;
}
public static double[][] grad2_field(double[][] arr){
int L=arr.length;
double[][] result=new double[L][L];
for(int i=0; i<L; i++){
for(int j=0; j<L; j++){
result[i][j]=grad2(arr, i, j);
}
}
return result;
}
static double[][]grad2u模具={{0,0,-1,0,0},
{0,0,16,0,0},
{-1,16,-60,16,-1},
{0,0,16,0,0},
{0,0,-1,0,0} };
公共静态双梯度2(双[][]数组,整数x,整数y){
双温=0;
int L=数组长度;
对于(int i=0;i,从当前github上的clojure 1.3分支开始,您可以从函数返回。您也不再需要键入提示编号原语。这将使提示此类代码的速度更快,看起来更优雅
在暗示这一点的类型中,您可能会遇到这样一个事实:(另一个有帮助的部分(也在1.3中)是静态函数链接,它将使一些函数调用与方法调用一样快(这也在链接中描述)
目前,以真正惯用的方式(即使用“map”高阶函数)编写此代码仍然很困难,因为高阶函数无法使用静态链接,但(无耻的插件警告)Rich Hickey希望纠正这一点:
在clojure 1.3(主分支)中尝试以下操作:
(def^”[[D”渐变2模具
(放入数组(类/forName“[D”)
(映射双数组)
[[ 0 0 -1 0 0 ]
[ 0 0 16 0 0 ]
[-1 16 -60 16 -1 ]
[ 0 0 16 0 0 ]
[ 0 0 -1 0 0 ]])))
(定义:静态idx^long[^long x^long i^long L]
(->x
(+i)
(- 2)
(mod L)
(+L)
(mod L)))
(定义:静态渐变2^双精度[^双精度arr^长x^长y]
(让[L(纵向arr)
温度(回路[i 0 j 0温度0.0]
(如果(
我尝试创建一个数组:(defa(到数组中(映射双数组(映射#)(重复L%1)(范围LЮ))),然后创建grad2函数:(time(grad2a1))但由于某些原因,它只是中止,我看不到任何堆栈跟踪。这到底是什么意思,函数参数被装箱了?我能够得到clojure代码,该代码添加了两个2d java数组,运行速度非常接近本机速度。据我现在所知,该函数从java中提取数字,在clojure中添加它们,然后推送结果back转换为java数组,类型提示用于clojure到java的交互。但是我的clojure版本的java代码做了同样的事情,只是在我将事情推回到java之前clojure中有更多的操作。但是我不明白为什么额外的操作会使事情变得如此缓慢。当我说函数调用时,我指的是调用clojure函数。如果运行(my function 42:-P),则数字42是一个整数类实例,而不是基元int,即使键入hint也是如此。此外,clojure函数调用的返回类型始终是对象,而不是基元(在clojure 1.3之前)向clojure 1.3的转换可能会使一些大量数字函数的运行时间减少一个零。如果没有类型暗示,您将如何处理混合类型集合?@Hamish Grubijan:混合类型集合将所有内容存储为类型对象,并将任何基元框起来。如果您将集合传递给函数,则将调用非stat函数的ic版本,不传递原语。只有^:静态函数可以接受原语。您不必担心手动调用函数的静态版本。它是自动的。将函数映射到原语上非常好。静态函数是使用Primative作为参数或返回类型的先决条件没错,ey目前正在实现中。Rich在SF会议期间做出了区分,指出在JVM级别,它们不是严格耦合的——听起来他正在实现的原始支持在某种程度上可能与静态函数不紧密耦合。
(def ^"[[D" grad2-stencil
(into-array (Class/forName "[D")
(map double-array
[[ 0 0 -1 0 0 ]
[ 0 0 16 0 0 ]
[-1 16 -60 16 -1 ]
[ 0 0 16 0 0 ]
[ 0 0 -1 0 0 ]])))
(defn ^:static idx ^long [^long x ^long i ^long L]
(-> x
(+ i)
(- 2)
(mod L)
(+ L)
(mod L)))
(defn ^:static grad2 ^double [^doubles arr ^long x ^long y]
(let [L (alength arr)
temp (loop [i 0 j 0 temp 0.0]
(if (< i 5)
(let [a (idx x i L)
b (idx y j L)
temp (double (* (aget arr a b)
(aget grad2-stencil i j)))]
(if (< j 4)
(recur i (inc j) temp)
(recur (inc i) 0 temp)))
temp))]
(/ temp 12.0)))
(defn ^:static grad2-field ^"[[D" [^"[[D" arr]
(let [result (make-array Double/TYPE (alength arr) (alength arr))]
(loop [i 0 j 0]
(when (< i 5)
(aset result (grad2 arr i j) i j)
(if (< j 4)
(recur i (inc j))
(recur (inc i) 0))))
result))