Làm thế nào để chuyển đổi chuỗi lười biếng thành không lười biếng trong Clojure


95

Tôi đã thử cách sau trong Clojure, mong đợi để trả về lớp của một chuỗi không lười biếng:

(.getClass (doall (take 3 (repeatedly rand))))

Tuy nhiên, điều này vẫn quay trở lại clojure.lang.LazySeq. Dự đoán của tôi là điều đó doallkhông đánh giá toàn bộ trình tự, nhưng trả về trình tự ban đầu vì nó vẫn hữu ích cho việc ghi nhớ.

Vì vậy, phương tiện thành ngữ để tạo ra một chuỗi không lười biếng từ một người lười biếng là gì?


Tôi không là ai cả ngạc nhiên đã được hỏi tại sao bạn đang quan tâm về loại thực tế của giá trị trả vềdoall
tar

Bạn có thể chuyển đổi sang một vector:(vec (take 3 (repeatedly rand)))
Kris

Câu trả lời:


161

doalllà tất cả những gì bạn cần. Chỉ vì seqloại LazySeqcó không có nghĩa là nó có đánh giá đang chờ xử lý. Lazy seqs cache kết quả của chúng, vì vậy tất cả những gì bạn cần làm là đi bộ lazy seqmột lần (như doallvậy) để buộc tất cả và do đó hiển thị nó không lười biếng. seqkhông không buộc các bộ sưu tập được đánh giá.


2
Tôi đã thay đổi câu trả lời này thành câu trả lời được chấp nhận. Trên một lưu ý liên quan, bạn có thể xác định xem LazySeq đã được đánh giá trước đó bằng phương tiện nào chưa?
Tim Clemons

10
Tôi tin rằng bạn chỉ cần gọi realized?.
toofarsideways

1
Có lẽ nên có một realizehoạt động để phù hợp realized?.
Reut Sharabani

Tất cả đều rất tốt đẹp. Nhưng vì một số chức năng như contains?không quan tâm liệu bạn có nhận ra lazy seq hay không, điều này trả lời cho câu hỏi cụ thể như đã hỏi, nhưng ít hơn cho tiêu đề của câu hỏi.
matanster

75

Đây là một câu hỏi về phân loại học ở một mức độ nào đó. chuỗi lười biếng chỉ là một loại trình tự như một danh sách, vectơ hoặc bản đồ. Vì vậy, câu trả lời tất nhiên là "nó phụ thuộc vào loại chuỗi không lười biếng bạn muốn nhận được:
Hãy lựa chọn của bạn từ:

  • một chuỗi lười biếng cũ (được đánh giá đầy đủ) (doall ... )
  • một danh sách để truy cập tuần tự (apply list (my-lazy-seq)) OR (into () ...)
  • một vectơ để truy cập ngẫu nhiên sau này (vec (my-lazy-seq))
  • một bản đồ hoặc một tập hợp nếu bạn có một số mục đích đặc biệt.

Bạn có thể có bất kỳ loại trình tự nào phù hợp nhất với nhu cầu của bạn.


Đây là câu trả lời tốt nhất.
Felipe

4
Câu trả lời được chấp nhận là đúng về mặt kỹ thuật, nhưng câu trả lời này hữu ích nhất đối với tôi. Tôi đang cố gắng ánh xạ một hàm qua một vectơ và sau đó trích xuất kết quả vào một tệp và ngay cả sau khi gọi doall, tệp vẫn chứa "clojure.lang.LazySeq@address" thay vì nội dung của chuỗi. Gọi vec trên bản đồ giá trị được trả về giúp tôi có những gì tôi cần để đưa vào tệp.
Jesse Rosalia

1
@JesseRosalia Thật vui khi biết rằng phản hồi Rich Hickey duy nhất trong tất cả SO là đúng về mặt kỹ thuật. ;-)
Phil Cooper

(vec (my-lazy-seq))không phải là quá đẹp trong những tình huống như sau: (vec (json/parse-string "{\"foo\":\"bar\"}")) ;; => [["foo" "bar"]]Kể từ khi cheshirelựa chọn để tạo ra một lười biếng-seq từ(json/parse-string)
codeasone

Giảm nhẹ cho những điều trên là sử dụng háo hức(json/parse-string-strict)
codeasone

22

Gã Giàu này dường như biết chiếc áo choàng của mình và hoàn toàn đúng.
Nhưng tôi nghĩ đoạn mã này, sử dụng ví dụ của bạn, có thể là một bổ sung hữu ích cho câu hỏi này:

=> (realized? (take 3 (repeatedly rand))) 
false
=> (realized? (doall (take 3 (repeatedly rand)))) 
true

Thực tế loại không thay đổi nhưng nhận thức


2
Tuy nhiên, cần lưu ý rằng bạn không cần phải buộc toàn bộ chuỗi realized?phải trả về true. Ví dụ(let [r (range) r? (realized? r)] (doall (take 1 r)) [r? (realized? r)]) => [false true]
Alex Coventry,

22
Anh chàng giàu này: D haha
Nimrod

10
@nimrod :) tuy nhiên cách chơi chữ này có nghĩa là trong "hís clojure".
Peter

10
Cho những ai chưa biết, "The Rich guy" đã phát minh ra Clojure.
erturne

1
@AlexCoventry lợi nhuận ví dụ của bạn[true true]

7

Tôi tình cờ trong bài đăng trên blog này về việc doallkhông đệ quy. Đối với điều đó, tôi thấy bình luận đầu tiên trong bài đăng đã thực hiện thủ thuật. Một cái gì đó dọc theo dòng của:

(use 'closure.walk)
(postwalk identity nested-lazy-thing)

Tôi thấy điều này hữu ích trong một bài kiểm tra đơn vị nơi tôi muốn buộc đánh giá một số ứng dụng lồng nhau của mapđể buộc một điều kiện lỗi.


5
(.getClass (into '() (take 3 (repeatedly rand))))

3
Đây là một ý tưởng khủng khiếp. Nó đảo ngược seq đầu vào.
amalloy

3
Tất nhiên, trong trường hợp này đảo ngược đầu vào làm cho không có sự khác biệt, kể từ khi họ chỉ là 3 số ngẫu nhiên .... :-)
mikera
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.