2010-07-15 30 views
6

Tôi có một mã như thế này. Tôi có thể chạy điều này trong repl nhưng không thể từ dòng lệnh. Tôi đoán tôi đã có một vấn đề đánh giá lười biếng.Vấn đề đánh giá lười biếng


; items.clj 

(def items (ref [])) 

(defn init-items [] 
    (map 
    #(dosync 
     (alter items conj %)) 
    ["foo" "bar" "baz" ])) 

(init-items) 
(println (first @items)) 

$ java -jar clojure.jar items.clj 
$ nil 

trọng.

Trả lời

4

OK!

solution

Clojure không phải là động lực để chạy map chức năng trong init-items bởi vì có kết quả không trả lại. Tôi bọc nó vào một doall để buộc thực hiện, và mau.

+0

tôi làm việc. Cảm ơn rất nhiều. – Osman

+3

Thực tế 'dorun' phù hợp hơn với trường hợp này (' doall' giữ trên đầu của seq nó kết thúc tốt đẹp và trả về nó, trong khi 'dorun' loại bỏ nó từng bước và cuối cùng trả về' nil' - vì vậy nó phù hợp hơn với mã hiệu ứng phụ). –

+0

@Michal: Tất nhiên, bạn hoàn toàn chính xác. Tôi đã mặc một chút với Clojure nhưng chưa bao giờ đạt được trình độ cao, và bây giờ, thật đáng buồn, thậm chí nó bắt đầu rỉ sét. Cảm ơn vì sự đúng đắn của bạn! –

4

Một số lựa chọn thay thế:

Nếu bạn chỉ muốn thêm một loạt các mục vào một bộ sưu tập được tổ chức tại một Ref, bắt đầu một giao dịch mỗi mục và conj ing họ riêng là một chút lãng phí. Thay vào đó, bạn có thể làm

(defn init-items [] 
    (dosync (alter items into ["foo" "bar" "baz"]))) 

Nếu bạn có một số lý do để làm điều đó trong một thời trang một mục mỗi bước, tôi nghĩ rằng cách tiếp cận thành ngữ và thuận tiện nhất hiện nay sẽ được sử dụng doseq:

(defn init-items [] 
    (doseq [item ["foo" "bar" "baz"]] 
    (dosync (alter items conj item)))) 

(Hoặc bạn có thể di chuyển bọc toàn bộ doseq trong một dosync và không sử dụng dosync trong cơ thể của doseq.)

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