2015-05-22 10 views
5

Próbowałem uruchomić dwie funkcje czynnikowe z tego samego algorytmu, jeden w Scala, drugi w Clojure:Różnica między Scala REPL i Clojure REPL - kompilacja prędkość

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

-

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

Za pierwszym razem, gdy wprowadzam funkcję do REPL, Clojure ocenia (definicja funkcji, nie oblicza silni) bez zauważalnego opóźnienia; podczas gdy scala jeden zatrzymał się na krótki czas. (Chociaż bardzo, bardzo krótki, nadal zauważalny.)

Po zastosowaniu funkcji obliczania silni oba zwracają wynik bardzo szybko.

Chciałbym uzyskać podstawową wiedzę na temat REPL. Czy są jakieś różnice między dwoma REPL? Czy Scala REPL jest prawdziwym REPL?

Odpowiedz

10

REPL ma raczej konkretne znaczenie. "Prawdziwa REPL" to taka, która pasuje do następującego wzoru: Czytaj Eval Print Loop. Można zbudować REPL w clojure w kilku liniach:

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

Tutaj widzisz główne części prawdziwego replika. read-line odczytuje tekst z konsoli. read-string zamienia ten ciąg na dane (listy, wektory, liczby itd.). eval ocenia dane zwracające wynik, a println drukuje wynik.

Niektórzy twierdzą (i zgodzę się), że tylko te systemy, które wykonują te cztery kroki, kwalifikują się do replikacji. A niektórzy zwracają również uwagę, że Scala nie jest homoiconic, a więc nie może naprawdę replikacji.

Przez homoiconic mam na myśli to, że kompilator działa na tych samych strukturach danych tworzonych przez czytnik języka i manipulowanych przez podstawowe konstrukcje języka. Na przykład, jest to całkowicie poprawny kod Clojure:

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

Więc to jest sedno debaty nad „prawdziwych” REPLs. Tylko homoiczne języki, takie jak lisp (i być może prolog?) Mogą mieć prawdziwe REPL. Wszyscy inni powinni naprawdę nazywać się "interaktywnymi tłumaczami".

O ile prędkość idzie. Prawdopodobnie wynika to ze złożoności kompilatora. Kompilator Clojure to tylko około 10k lini ładnego liniowego kodu. Single pass, nic specjalnego. Kompilator Scala jest dość zaawansowany, obsługując takie rzeczy jak statyczne pisanie i wielokrotne przebiegi. Te dodatkowe funkcje nie są potrzebne w języku takim jak Clojure i mają tendencję do spowalniania kompilatora.

+1

Hmm. Pomyślałbym, że jeśli interakcja z wiersza poleceń obejmuje oddzielne odczytywanie, ocenianie i drukowanie, to wystarczyłoby dla REPL-ności, niezależnie od tego, czy jest to język homoiczny, czy nie. Nie nazwałbym czegoś interpretatorem, jeśli kompiluje się przed wykonaniem. Oczywiście istnieje wiele pośrednich przypadków między "wykonaniem jednego wyrażenia w tym samym czasie, jednym po drugim" i "przetłumacz i zoptymalizuj duże fragmenty kodu do pewnego rodzaju języka" komputerowego ", a następnie wykonaj". Jednak nie sądzę, aby to miało jakikolwiek wpływ! – Mars

+0

Powiązane: http://stackoverflow.com/questions/5671214/is-lisp-the-only-language-with-repl –