2012-10-19 18 views
8

Używam klasy Java, która reprezentuje sekwencję wyników (trochę jak wektor Clojure).Ustaw klasę Java jako sekwencję w Clojure

Chciałbym użyć tej klasy z typowymi funkcjami sekwencji Clojure (tj. Chcę, aby klasa zachowywała się tak, jakby obsługiwała abstrakcję sekwencji), jednak I nie może zmienić klasy, więc nie jestem w stanie jej wykonać implementacja clojure.lang.Seqable lub podobna. Ponadto, irytująco, klasa nie implementuje java.util.Collection lub java.lang.Iterable.

Widzę kilka możliwości:

  • Zastosowanie iterator-seq ON (istniejącego) iterator obiektu.
  • Wrap przedmiot w innej klasy, która implementuje java.util.Collection/clojure.lang.Sequable
  • utworzyć funkcję, która buduje wektor Clojure lub sekwencji przez odpytywanie Object

Czy są jakieś inne opcje? Jakie jest najlepsze podejście?

+1

'iterator-seq' wydaje się być w porządku, wewnętrznie robi to samo, co drugi punkt dotyczący zawijania obiektu – Ankur

Odpowiedz

6

Najszybszym i najprostszym rozwiązaniem byłoby użycie iterator-seq.

To powoduje, że pojawia się pytanie: Dlaczego rdzeń Clojure nie zapewnia protokołu takiego jak SeqSource, który zostałby nazwany przez seq. Następnie niestandardowe kolekcje mogą być "rozszerzone", aby dostarczyć seq, podobnie jak działa InternalReduce dla reduce.

+7

Ponieważ seq jest (a) używane przez kompilator, a zatem musi być przyjazne dla java (tzn. interfejs), a także (b) nazywany bardzo, bardzo często, tak że musi być tak szybki, jak to możliwe - protokoły są szybsze niż wiele rzeczy, ale nie tak szybkie, jak prosta wysyłka interfejsu. – amalloy

+0

@amalloy następnie może funkcja 'to-seq' zamiast –

+0

" Ponadto, irytująco, klasa nie implementuje java.util.Collection lub java.lang.Iterable. " – noahlz

2

Mój pierwszy strzał byłoby stworzenie leniwe-seq tego obiektu:

(defn sequify [obj] 
    (letfn [(inner [idx] 
       (when (< idx (.size obj)) 
          (cons (.get obj idx) 
           (lazy-seq 
            (inner (inc idx))))))] 
    (inner 0))) 

Wystarczy zastąpić .size i .get z odpowiednimi metodami.

Pisanie obwoluty może być bardziej odpowiednie, jeśli chcesz poprawić wydajność w porównaniu do rozwiązania lazy-seq.