2013-04-28 23 views
10

Có cách nào để xác định liệu một LazySeq có chứa một phần tử không? Tính đến Clojure 1,5 gọi contains? ném một IllegalArgumentException:Clojure: Cách thành ngữ để gọi có chứa? trên một trình tự lười biếng

IllegalArgumentException contains? not supported on type: clojure.lang.LazySeq  
clojure.lang.RT.contains (RT.java:724) 

Trước 1.5, như xa như tôi biết, nó luôn được trả về sai.

Tôi biết rằng gọi contains? trên LazySeq có thể không bao giờ trở lại vì nó có thể là vô hạn. Nhưng nếu tôi biết nó không phải là và không quan tâm nếu nó được đánh giá háo hức?

Những gì tôi đã đưa ra là:

(defn lazy-contains? [col key] 
    (not (empty? (filter #(= key %) col)))) 

Nhưng nó không cảm thấy hoàn toàn đúng. Có cách nào tốt hơn?

Trả lời

11

Đầu tiên, các địa chỉ email lười biếng không hiệu quả để kiểm tra tư cách thành viên. Hãy xem xét sử dụng một bộ thay vì một seq lười biếng.

Nếu tập hợp không thực tế, giải pháp của bạn không phải là xấu. Một vài cải tiến có thể có:

  1. "Không trống" hơi khó xử. Chỉ cần sử dụng seq là đủ để có được một giá trị nil-hoặc-truthy mà người dùng của bạn có thể sử dụng trong một if.You có thể bọc rằng trong boolean nếu bạn muốn đúng hay sai.

  2. Vì bạn chỉ quan tâm đến trận đấu đầu tiên, bạn có thể sử dụng một số thay vì lọc và seq.

  3. Một cách thuận tiện để viết một vị ngữ bình đẳng là với một tập hợp chữ, như # {key}, mặc dù nếu khóa là nil, điều này sẽ luôn trả về nil cho dù nil được tìm thấy không.

Tất cả cùng nhau cung cấp cho bạn:

(defn lazy-contains? [col key] 
    (some #{key} col)) 
+0

Trường hợp có nil là khóa làm cho nó có phần không chính xác. Nhưng vì trong trường hợp của tôi chìa khóa không bao giờ là nil tôi có thể sống với nó. – nansen

+0

Phải. Để khắc phục điều đó, chỉ cần sử dụng biến vị ngữ ban đầu của bạn: (một số # (= key%) col) – Chouser

+0

@Chouser Tôi đã cố gắng triển khai bất kỳ lựa chọn thay thế nào cho một mục đích cụ thể và đã chạy vào vấn đề sau. Làm thế nào tôi sẽ nhận được điều này để phù hợp hơn với bản gốc có chứa? chức năng? (lười biếng chứa? {: Trạng thái "hoạt động",: course_n "law",: course_i "C0"}: trạng thái) trả về nil nhưng khi sử dụng có chứa? nó trả về true Tôi đang cố gắng để grok thông qua clojuredocs là tốt và không thấy làm thế nào để sửa chữa nó. – RatavaWen

4

Nếu bạn sử dụng some thay vì filter như trong ví dụ của mình, bạn sẽ nhận được ngay lập tức trở lại ngay khi tìm thấy giá trị thay vì buộc đánh giá toàn bộ chuỗi.

(defn lazy-contains? [coll key] 
    (boolean (some #(= % key) coll))) 

Sửa: Nếu bạn không ép buộc kết quả vào một boolean, lưu ý rằng bạn sẽ nhận được nil thay vì false nếu phím không được tìm thấy.

+0

Sử dụng bộ lọc như tôi đã không đánh giá toàn bộ chuỗi miễn là giá trị được tìm thấy đầu tiên. '(lazy-contains? (range) 100)' trả về true. Vậy nó có tương đương với chức năng của bạn không? – nansen

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