我刚开始学习Clojure。我注意到的第一件事是没有循环。没关系,我可以使用recur。那么让我们看看这个函数(来自《实用Clojure》):
(defn add-up
"Adds up numbers from 1 to n"
([n] (add-up n 0 0))
([n i sum]
(if (< n i)
sum
(recur n (+ 1 i) (+ i sum)))))
为了在Javascript中实现相同的功能,我们使用循环,如下所示:
function addup (n) {
var sum = 0;
for(var i = n; i > 0; i--) {
sum += i;
}
return sum;
}
计时后,结果看起来像:
input size: 10,000,000
clojure: 818 ms
nodejs: 160 ms
input size: 55,000,000
clojure: 4051 ms
nodejs: 754 ms
input size: 100,000,000
clojure: 7390 ms
nodejs: 1351 ms
在阅读了这篇文章之后,我开始尝试经典的斐波那契数列实现:
在Clojure中:
(defn fib
"Fib"
[n]
(if (<= n 1) 1
(+ (fib (- n 1)) (fib (- n 2)))))
在 JavaScript 中:
function fib (n) {
if (n <= 1) return 1;
return fib(n-1) + fib(n-2);
}
再次强调,性能有相当大的差异。
fib of 39
clojure: 9092 ms
nodejs: 3484 ms
fib of 40
clojure: 14728 ms
nodejs: 5615 ms
fib of 41
clojure: 23611 ms
nodejs: 9079 ms
注意:我正在使用Clojure中的(time (fib 40)),因此它忽略了JVM的启动时间。这些代码在MacBook Air(1.86 GHz Intel Core 2 Duo)上运行。
那么是什么导致Clojure在这里变慢了?为什么人们说“Clojure很快”?
非常感谢,在此先行致谢,请勿引发无意义的争论。