2012-02-10 56 views
12

Tôi đang sử dụng thư viện Sesame để chạy các truy vấn SPARQL qua một cửa hàng ba bộ nhớ trong.Làm thế nào để biến một đối tượng giống như Iterator java thành một chuỗi clojure

Tôi đang sử dụng Clojure để đạt được điều này.

Kết quả truy vấn là đối tượng Iterator giống như [1] tùy chỉnh, do đó, clojure seq không hoạt động trên đó.

Cách thanh lịch nhất để biến một Iterator java tùy chỉnh như đối tượng thành chuỗi thứ tự clojure là gì?

Ý tưởng rõ ràng và ngu ngốc nhất đã đến với tâm trí của tôi là lặp lại nó và xây dựng một vector clojure, nhưng tôi chắc chắn có cách tiếp cận thanh lịch hơn cho vấn đề này.

[1] http://www.openrdf.org/doc/sesame2/api/info/aduna/iteration/Iteration.html

Trả lời

8

Phiên bản thử nghiệm:

(defn iteration->seq [iteration] 
(seq 
    (reify java.lang.Iterable 
     (iterator [this] 
     (reify java.util.Iterator 
      (hasNext [this] (.hasNext iteration)) 
      (next [this] (.next iteration)) 
      (remove [this] (.remove iteration))))))) 
+2

Điều này (reifying Iterable thay vì Iterator) là một cách tiếp cận; khác là để reify Iterator và sau đó bọc nó với ['iterator-seq'] (http://clojuredocs.org/clojure_core/clojure.core/iterator-seq). – amalloy

+0

Tốt, rất tốt để biết! – laczoka

5

Làm thế nào về gói các đối tượng iterator giống như trong một đối tượng mà thực sự thực hiện các giao diện Iterator? Một cái gì đó như sau (không kiểm tra):

(defn iteration-seq [iteration] 
    (iterator-seq 
    (reify java.util.Iterator 
    (hasNext [this] (.hasNext iteration)) 
    (next [this] (.next iteration)) 
    (remove [this] (.remove iteration))))) 

Theo như tôi có thể nói, lợi thế duy nhất (nếu bạn muốn gọi nó đó) của giao diện Iteration so với giao diện chuẩn Iterator là nó cho phép để khai báo ngoại lệ đã kiểm tra, không được sử dụng trong Clojure anyways.

[Update: Sửa mã để sử dụng iterator-seq thay vì seq, theo đề nghị của @amalloy trong một bình luận về câu trả lời khác.]

+0

Cảm ơn. Không hoàn toàn, nhưng nó chỉ cho tôi đi đúng hướng và giúp tôi tìm hiểu về cách sử dụng thực tế của * reify *. – laczoka

+0

Tôi đã có phiên bản chính xác đã được kiểm tra, không thể tự trả lời do một số hạn chế về danh tiếng. :) – laczoka

1

tinh khiết chức năng iterable-to- mã trình tự lười biếng cho java Iterable và Iterator

(defn iter-seq 
    ([iterable] 
    (iter-seq iterable (.iterator iterable))) 
    ([iterable i] 
    (lazy-seq 
     (when (.hasNext i) 
     (cons (.next i) (iter-seq iterable i)))))) 

Đối với các trình vòng lặp tùy chỉnh thay thế .iterator, .hasNext và .next calls.

Lợi thế là nó hoàn toàn hoạt động vì nó có thể lặp lại làm đối số. Các giải pháp được đăng khác có tham số vòng lặp có thể thay đổi để hàm có thể trả về một chuỗi khác nhau tùy thuộc vào trạng thái của trình lặp nội bộ vi phạm referential transparency. Chức năng này cũng rực rỡ về sự lười biếng của nó.

1

Tại sao không cung cấp cho clojure.core/iterator-seq một lần thử?

user=> (doc iterator-seq) 
------------------------- 
clojure.core/iterator-seq 
([iter]) 
    Returns a seq on a java.util.Iterator. Note that most collections 
    providing iterators implement Iterable and thus support seq directly. 

Như bạn thấy trong chuỗi tài liệu ở trên, bạn thậm chí có thể không cần sử dụng iterator-seq một cách rõ ràng. Bạn đã thử xử lý Java iterator của bạn như là một chuỗi trong REPL?

+0

Điều này không hoạt động như iterator-seq rõ ràng chỉ hoạt động với java.util.Iterator, trong khi đối tượng được mô tả ở đây là một info.aduna.iteration.Iteration. Sử dụng iterator-seq dẫn đến một ClassCastException. – PaulaG

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