2013-08-27 33 views
7

Tôi hiện đang đọc cuốn sách lập trình O'reilly Clojure mà nó nói như sau trong đó là phần về chuỗi lười biếng:Làm thế nào để tìm chiều dài của chuỗi chậm mà không buộc phải thực hiện?

Có thể (mặc dù rất hiếm) cho một chuỗi lười biếng để biết chiều dài của nó, và do đó trả về kết quả đếm mà không nhận ra nội dung của nó.

Câu hỏi của tôi là, Điều này được thực hiện như thế nào và tại sao nó lại quá hiếm?

Thật không may, cuốn sách không chỉ định những điều này trong phần này. Cá nhân tôi nghĩ rằng nó rất hữu ích để biết độ dài của một chuỗi lười biếng trước khi nó thực hiện, ví dụ, trong cùng một trang là một ví dụ về một chuỗi các tập tin lười biếng được xử lý với một chức năng sử dụng map. Nó sẽ được tốt đẹp để biết có bao nhiêu tập tin có thể được xử lý trước khi thực hiện trình tự.

Trả lời

7

Tôi cho rằng đó là do thực tế thường có nhiều cách khác để tìm ra kích thước.

Việc triển khai chuỗi duy nhất tôi có thể nghĩ bây giờ có khả năng làm điều đó, là một loại bản đồ của hàm/thủ tục tốn kém trên một bộ sưu tập kích cỡ đã biết.

Triển khai đơn giản sẽ trả về kích thước của bộ sưu tập cơ bản, trong khi trì hoãn việc thực hiện các phần tử của chuỗi lười (và do đó thực hiện phần đắt tiền) cho đến khi cần thiết.

Trong trường hợp đó, người ta biết kích thước của bộ sưu tập đang được ánh xạ trước và có thể sử dụng bộ sưu tập đó thay vì kích thước lazy-seq.

Đôi khi nó có thể hữu ích và đó là lý do tại sao nó không phải là không thể thực hiện, nhưng tôi đoán hiếm khi cần thiết.

+1

Rõ ràng đây không phải là ví dụ duy nhất có thể. Điều gì về '(lặp lại 1000 x)'? '(dải 100)'? Có nhiều loại trình tự lười biếng * có thể * biết chiều dài của chúng, nhưng không có nó được lập trình đơn giản bởi vì nó sẽ mất thời gian kỹ thuật và có thời gian chạy trên một lợi thế có thể nhỏ. – amalloy

+0

@amalloy đó là lý do tại sao tôi nói "tôi có thể nghĩ đến", có lẽ tôi nên thêm "bây giờ" ở cuối :) Vẫn phần còn lại của câu trả lời giữ - chiều dài của chuỗi lười biếng được biết trước khi tạo ra nó để không có thực sự đạt được trong khéo léo thực hiện chiều dài trong chuỗi chính nó. – soulcheck

+0

Điều này có nghĩa là không thể đếm mà không nhận ra một chuỗi lười biếng là kết quả của một 'bộ lọc'? Nói một số phần tử ngẫu nhiên của một vài triệu số ngẫu nhiên: '(- >> my-rand-int-lazy-seq (bộ lọC# (thậm chí?%)) (Đếm-không-thực hiện))'? – adamneilson

9

Được lấy cảm hứng từ soulcheck's answer, đây là bản đồ lười nhưng được tính của một hàm đắt tiền so với bộ sưu tập kích thước cố định.

(defn foo [s f] 
    (let [c (count s), res (map f s)] 
    (reify 
     clojure.lang.ISeq 
     (seq [_] res) 
     clojure.lang.Counted 
     (count [_] c) 
     clojure.lang.IPending 
     (isRealized [_] (realized? res))))) 


(def bar (foo (range 5) (fn [x] (Thread/sleep 1000) (inc x)))) 

(time (count bar)) 
;=> "Elapsed time: 0.016848 msecs" 
; 5 

(realized? bar) 
;=> false 


(time (into [] bar)) 
;=> "Elapsed time: 4996.398302 msecs" 
; [1 2 3 4 5] 

(realized? bar) 
;=> true 

(time (into [] bar)) 
;=> "Elapsed time: 0.042735 msecs" 
; [1 2 3 4 5] 
+0

+1 để triển khai ví dụ – soulcheck

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