2013-06-29 54 views
5

Cho luồng đầu vào, tôi muốn tạo một chuỗi dữ liệu lười ở dạng byte-mảng (khối). Dưới đây là cố gắng của tôi:Clojure: Tạo một chuỗi khối byte lười từ luồng đầu vào

(defn- read-or-nil [stream] 
    (let [buf (byte-array 2)] 
    (when-not (= -1 (.read stream buf)) 
     buf))) 

(defn byte-chunk-seq [stream] 
    (cons (read-or-nil stream) (lazy-seq (byte-chunk-seq stream)))) 

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")]                                               
    (take 2 (byte-chunk-seq rdr))) 

Trong tuyên bố mới nhất, nơi tôi đang thử nghiệm mã, tôi nhận được một:

IOException Suối Closed java.io.FileInputStream.readBytes (FileInputStream.java:-2).

Nếu tôi thay đổi tuyên bố thành take 1 thì nó sẽ trả về tiền phạt, nhưng điều đó không giúp ích gì cho tôi nhiều. Có ai có bất kỳ ý tưởng tại sao điều này sẽ không làm việc?

Trả lời

4

Có một vài vấn đề.

Đầu tiên, trình tự lười biếng của bạn không hoàn toàn chính xác. Toàn bộ phần thân của hàm nên được bọc trong lazy-seq và nó sẽ truyền vào hoặc là điểm yếu để tiếp tục trình tự, hoặc không kết thúc nó.

(defn byte-chunk-seq [stream] 
    (lazy-seq (if-let [buf (read-or-nil stream)] 
       (cons buf (byte-chunk-seq stream)) 
       nil))) 

Thứ hai, take cũng lười. Vì vậy, trình tự lười biếng sẽ không được thực hiện cho đến sau khi with-open đã đóng luồng. Bạn có thể tránh lỗi này bằng cách gói một số doall xung quanh chuỗi lười để nhận ra nó trước khi luồng được đóng.

(with-open [rdr (java.io.FileInputStream. "/tmp/wut")] 
    (doall (take 2 (byte-chunk-seq rdr))))