2015-05-22 11 views
5

Tôi cố gắng để chạy hai chức năng thừa với các thuật toán tương tự, một ở Scala, người kia trong Clojure:Sự khác nhau giữa Scala REPL và Clojure REPL - biên dịch tốc độ

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

-

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

Lần đầu tiên tôi nhập hàm vào REPL, một hàm Clojure đánh giá (định nghĩa hàm, không tính giai thừa) mà không có bất kỳ sự chậm trễ đáng chú ý nào; trong khi scala chỉ dừng lại trong một thời gian ngắn. (Mặc dù rất, rất ngắn, vẫn đáng chú ý.)

Khi tôi áp dụng hàm để tính giai thừa, cả hai đều trả lại kết quả rất nhanh.

Tôi muốn hiểu rõ hơn về REPL. Có bất kỳ sự khác biệt nào giữa hai REPL không? Là Scala REPL một REPL thực?

Trả lời

10

REPL có ý nghĩa khá cụ thể. "True REPL" sẽ là một mẫu phù hợp với mẫu sau: Đọc Đánh giá vòng lặp in. Người ta có thể xây dựng một REPL trong clojure chỉ trong một vài dòng:

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

Ở đây bạn sẽ thấy các phần chính của một repl thực sự. read-line đọc một số văn bản từ bảng điều khiển. read-string chuyển đổi chuỗi đó thành dữ liệu (danh sách, vectơ, số, v.v.). eval đánh giá dữ liệu trả lại kết quả và println in kết quả.

Một số người sẽ tranh luận (và tôi đồng ý) rằng chỉ những hệ thống tuân theo bốn bước này mới đủ điều kiện được gọi là repl. Và một số cũng chỉ ra rằng Scala không phải là đồng âm, và vì vậy không thể thực sự có một repl.

Bằng homoiconic, tôi có nghĩa là trình biên dịch hoạt động trên cùng cấu trúc dữ liệu được tạo ra bởi trình đọc của ngôn ngữ và được xử lý bởi cấu trúc cốt lõi của ngôn ngữ. Ví dụ: đây là mã Clojure hoàn toàn hợp lệ:

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

Vì vậy, đó là ý chính của cuộc tranh luận về REPLs "thực". Chỉ những ngôn ngữ đồng âm như lisp (và có lẽ prolog?) Mới có thể có REPL thực sự. Tất cả những người khác thực sự nên được đặt tên là "thông dịch viên tương tác".

Theo như tốc độ đi. Đó có thể là do sự phức tạp của trình biên dịch. Trình biên dịch Clojure chỉ là khoảng 10k dòng mã khá tuyến tính. Vé đơn, không có gì đặc biệt. Trình biên dịch Scala khá tiên tiến, hỗ trợ những thứ như gõ tĩnh và nhiều lần truyền. Những tính năng phụ không cần thiết trong một ngôn ngữ như Clojure, và chúng có xu hướng làm chậm trình biên dịch xuống một chút.

+1

Hmm. Tôi đã nghĩ rằng nếu một tương tác dòng lệnh liên quan đến các bước đọc, đánh giá và in riêng biệt, điều đó là đủ cho REPL-Ness, cho dù ngôn ngữ có đồng âm hay không. Tôi sẽ không gọi cho ai đó thông dịch nếu nó biên dịch trước khi thực hiện. Tất nhiên, có tất cả các loại trường hợp trung gian giữa "thực hiện một biểu thức tại một thời điểm, cái khác" và "dịch và tối ưu hóa các phần lớn mã xuống một số loại ngôn ngữ 'máy', và sau đó thực hiện". Tuy nhiên, tôi không nghĩ rằng bất kỳ điều này quan trọng lắm! – Mars

+0

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

Các vấn đề liên quan