Các docstrings cho first
và rest
nói rằng các chức năng gọi seq
trên lập luận của mình để truyền đạt ý tưởng rằng bạn không cần phải gọi seq
mình khi đi qua trong một bộ sưu tập seqable mà không phải là của riêng mình một seq, như, nói , một véc tơ hoặc bộ. Ví dụ:
(first [1 2 3])
;= 1
sẽ không hoạt động nếu first
không gọi seq
về đối số của nó; bạn cần phải nói số
(first (seq [1 2 3]))
thay vào đó, điều này sẽ bất tiện.
Cả hai take
và drop
cũng gọi seq
trên đối số của chúng, nếu không bạn không thể gọi chúng trên vectơ và tương tự như đã giải thích ở trên. Trên thực tế, điều này đúng với tất cả các bộ sưu tập seq tiêu chuẩn - những bộ phận không gọi trực tiếp là seq
được xây dựng dựa trên các thành phần cấp thấp hơn.
Không có cách nào điều này làm giảm sự lười biếng của các địa chỉ lười biếng. Việc bắt buộc/thực hiện xảy ra là kết quả của cuộc gọi first
/rest
là số tiền nhỏ nhất có thể để có được kết quả được yêu cầu. (Điều đó phụ thuộc vào loại đối số như thế nào, nếu nó không thực sự là lười biếng, không có sự thực hiện thêm nào liên quan đến cuộc gọi first
; nếu nó là một phần lười biếng - đó là, chunked - sẽ có thêm một số thực hiện (lên đến 32 yếu tố ban đầu sẽ được tính cùng một lúc), nếu nó hoàn toàn lười biếng, chỉ có các yếu tố đầu tiên sẽ được tính toán.)
Rõ ràng , khi thông qua một seq lười, phải buộc thực hiện yếu tố đầu tiên của nó - - đó là toàn bộ vấn đề. rest
thực sự là hơi lười ở chỗ nó thực sự không bắt buộc thực hiện phần "phần còn lại" của seq (đó là trái ngược với next
, về cơ bản tương đương với (seq (rest ...))
). Thực tế là nó buộc yếu tố đầu tiên được nhận ra để nó có thể bỏ qua nó ngay lập tức là một sự lựa chọn thiết kế có ý thức mà tránh lớp không cần thiết của các đối tượng seq lười biếng và giữ đầu của seq gốc; bạn có thể nói điều gì đó như (lazy-seq (rest xs))
để trì hoãn ngay cả việc thực hiện ban đầu này, với chi phí giữ cho đến xs
cho đến khi nhận ra trình bao bọc seq lười biếng được nhận ra.
Nguồn
2013-08-06 02:49:44
Cảm ơn vì điều đó. Tôi nghĩ đó là sự khác biệt giữa chunked và lười biếng hoàn toàn đã ném tôi đi. Đặc biệt khi tôi lần đầu tiên làm việc với lazy-seq tôi nghĩ rằng bất cứ điều gì tôi đã làm việc trên phải đã gây ra vấn đề khi chunked vì vậy tôi chỉ bị mắc kẹt với nó sau đó. – robertjlooby
Có, chunking có thể dẫn đến kết quả bất ngờ nếu một người quên nó. 'take' sử dụng cả' first' và 'rest' trong quá trình thực hiện, trong khi' drop' được xây dựng trên 'rest', vì vậy chúng không giúp ích gì.Unchunking là có thể, nhưng chỉ theo nghĩa là người ta có thể gây ra các phép biến đổi được xếp chồng lên nhau trên các phần tử bị chẻ được đánh giá một phần tử tại một thời điểm; các seq chunked cơ bản sẽ luôn luôn nhận ra khối của nó đầy đủ. (Cách để làm điều đó là để quấn các seq chunked trong một seq unchunking, có lẽ sản xuất với '(reify clojure.lang.ISeq ...)' với seq ban đầu trong một đóng cửa.) –
Bạn có chắc 'take'/'drop' cũng thực sự gọi là' seq'? Chỉ cần thử nó trong repl và gọi 'class' với' (range) ',' (take 1 (range)) ',' (drop 1 (range)) 'tất cả cho' clojure.lang.LazySeq'. Gọi với '(phần còn lại (khoảng))', '(seq (dải))' cho 'clojure.lang.ChunkedCons'. – robertjlooby