2010-06-24 13 views
14

Zajmuję się tworzeniem złożonych struktur danych w Clojure z wieloma podstrukturami.Abstrahowanie od szczegółów implementacji struktury danych w Clojure

Wiem, że będę chciał rozszerzyć tę strukturę w czasie, i czasami może chcieć zmienić wewnętrzną strukturę bez łamania różnych użytkowników struktury danych (na przykład mogę chcieć zmienić wektor na mieszańca, dodać jakiś rodzaj struktury indeksowania ze względu na wydajność, lub włączyć typu Java)

Mój obecny myślenie jest:

  • Określ protokół dla ogólnej struktury z różnych metod dostępowych
  • Tworzenie mini-bibliotekę funkcje nawigujące po strukturze danych e .sol. (Zapytanie-podbudowa-abc param1 param2)
  • Wdrożenie struktury danych przy użyciu defrecord lub deftype, z metod określonych protokołów korzystać z mini-biblioteki

myślę, że to będzie działać, choć obawiam się, że zaczyna wyglądać raczej jak dużo "kleju" kodu. Prawdopodobnie odzwierciedla to również moją większą znajomość podejść zorientowanych obiektowo.

Jaki jest zalecany sposób zrobienia tego w Clojure?

Odpowiedz

11

Myślę, że to może być droga, ale ja bym przeszedł na metody dostępu. Zamiast tego spójrz na clojure.lang.ILookup i clojure.lang.Associative; są to interfejsy, które, jeśli zastosujesz je dla swojego typu, pozwolą ci użyć get/i assoc/assoc-in, tworząc o wiele bardziej uniwersalne rozwiązanie (nie tylko będziesz w stanie zmienić podstawową implementację, ale być może także użyć funkcje zbudowane na bazie standardowej biblioteki kolekcji Clojure do manipulowania twoimi strukturami).

Kilka rzeczy do uwaga:

  1. Powinieneś raczej zacząć defrecord korzystając get, assoc & Co. ze standardowymi defrecord implementacjach ILookup, Associative, IPersistentMap i java.util.Map. Możesz być w stanie przejść z tym długą drogę.

    Jeśli/kiedy nie są wystarczające, spójrz na źródła dla emit-defrecord (prywatna funkcja zdefiniowana w core_deftype.clj w źródłach Clojure). Jest to dość skomplikowane, ale daje pojęcie o tym, co może być potrzebne do wdrożenia.

  2. Obecnie deftype ani defrecord nie definiują dla ciebie żadnych funkcji fabrycznych, ale prawdopodobnie powinieneś zrobić to sam. Sprawdzanie psu wchodzi w te funkcje (i/lub odpowiednie testy).

  3. Bardziej koncepcyjnie skomplikowane operacje są oczywiście idealne dopasowanie do funkcji protokołu zbudowany na fundamencie get & Co.

Aha, i spojrzeć na gvec.clj w źródłach Clojure dla przykładu jak mógłby wyglądać jakiś poważny kod struktury danych napisany przy użyciu deftype.Złożoność różni się od tego, co opisujesz w pytaniu, ale jest to jeden z niewielu przykładów niestandardowego programowania struktury danych w Clojure, który jest obecnie dostępny do publicznej konsumpcji (i jest to oczywiście kod doskonałej jakości).

Oczywiście to właśnie podpowiada mi moja intuicja. Nie jestem pewien, czy na tym etapie jest wiele ustalonych idiomów, a co z tym, że deftype właściwie się nie wydało i wszystko. :-)

+0

Dzięki Michał! Wnikliwe jak zawsze :-) z pewnością zajrzy do opcji ILookup i asocjacyjnych – mikera

+0

Jest to bardzo przydatna odpowiedź! Ale prawie trzy lata później byłoby świetnie zaktualizować to (lub utworzyć nową odpowiedź) w oparciu o funkcję dostępną teraz w wersji 1.5. Jedną z rzeczy, którą zauważyłem jest to, że 'defrecord' obecnie emituje funkcje fabryczne, nie wiem, jakie inne zmiany mogą wpłynąć na tę odpowiedź. –

+0

Myślę, że ta odpowiedź mogłaby również użyć aktualizacji - nawet książka O'Reily Clojure mówi teraz, że defrordor clojure tworzy funkcje fabryczne. – djhaskin987