2015-05-22 107 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 –