2015-05-22 81 views
5

我试图用相同的算法运行两个因子的功能,一个Scala中,对方用Clojure:差异 - 编译速度

// Scala: 
def factorial(n:Int) = (1 to n).foldLeft(1: BigInt)(_*_) 

-

;; Clojure: 
(defn factorial [x] 
    (reduce * (range 1N (inc x)))) 

当我第一次进入REPL的函数时,Clojure会评估(函数定义,而不是计算阶乘),没有任何明显的延迟;而斯卡拉的一个短暂停顿了一会儿。 (虽然非常非常短,但仍然引人注意)。

当我应用函数来计算阶乘时,两者都返回结果的速度非常快。

我想对REPL有一个基本的了解。两个REPL有什么区别? Scala REPL是一个真正的REPL吗?

回答

10

REPL有一个相当具体的含义。 “True REPL”将符合以下模式:阅读Eval打印循环。我们可以在几行文件中构建一个REPL文件:

(loop [] 
    (let [string (read-line) 
     data (read-string line) 
     result (eval data)] 
    (println result) 
    (recur))) 

这里您会看到一个真正的repl的主要部分。 read-line从控制台读取一些文本。 read-string将该字符串转换为数据(列表,向量,数字等)。 eval评估返回结果的数据,并打印结果println。有些人会争论(我同意),只有遵循这四个步骤的系统才有资格被称为repl。有些人还会指出Scala并不是同质的,所以不能真正拥有一个repl。

通过homoiconic,我的意思是说,编译器对语言阅读器产生的相同数据结构进行操作,并且受到语言核心构造的控制。例如,这是完全合法的Clojure代码:

(eval (list (symbol "+") 41 1))) ; evals to 42 

所以这是在“真正的” REPLs争论的要点。只有homoiconic语言(如lisp(也许是prolog?)才能有真正的REPL。所有其他人都应该被称为“互动口译员”。

就速度而言。这可能是由于编译器的复杂性。 Clojure编译器只有大约10k行非常线性的代码。单传,没什么特别的。 Scala编译器非常先进,支持静态类型和多次传递。这些额外的功能在Clojure这样的语言中是不需要的,而且它们往往会使编译器慢一点。

+1

嗯。如果命令行交互涉及单独的读取,评估和打印步骤,那么我认为这对于REPL性能来说已经足够了,无论这种语言是同相还是不同步。如果在执行之前编译,我不会调用某个解释器。当然,在“一次一个,一个接一个地执行一个表达式”和“将大块代码翻译并优化成某种'机器'语言,然后执行”之间的各种中间情况。但是,我不认为这很重要! – Mars

+0

相关:http://stackoverflow.com/questions/5671214/is-lisp-the-only-language-with-repl –