2011-02-16 10 views
7

Najwyraźniej nie można nazwać stosuje się konstruktora rekordu:Konstruktorzy rekordów Clojure nie są pierwszymi klasami?

(defrecord Foo. [id field]) 

(apply Foo. my-list) 

nie w momencie odczytu, ponieważ nie spodziewa Foo. w tamtym miejscu.

Jedynym oczywiste obejście mogłem pomyśleć było dodać funkcję fabryczną:

(make-foo [id field] (Foo. id field)) 

które można apply'ed oczywiście.

Czy brakuje mi czegoś? Spodziewałbym się tego od C#/Java, ale pomyślałem, że było to trochę rozczarowujące w Clojure ...

+0

zgadzają się, że jest trochę na osobliwość, ale osobiście nigdy nie było problemem, ponieważ uważam funkcje fabryczne raczej użyteczny - ten wzór obsługuje bardziej idiomatyczne użycie Clojure, zapewnia większą elastyczność w parametrach przetwarzania wstępnego, pozwala na różne zestawy konstruktorów do różnych celów, zapewnia warstwę abstrakcji itp. – mikera

Odpowiedz

10

Krążąc z powrotem na ten post-1.3 ....

W Clojure 1.3, defrecord tworzy dwa wygenerowane funkcji konstruktora. Biorąc pod uwagę:

(defrecord Person [first last]) 

to stworzy pozycyjną funkcję konstruktora ->Person:

(->Person "alex" "miller") 

i funkcję map konstruktora map->Person:

(map->Person {:first "string"}) 

Ponieważ jest to mapa, wszystkie przyciski są opcjonalne i przyjmują wartość zerową w skonstruowanym obiekcie.

Powinieneś wymagać/używać tych funkcji z ns, w którym deklarujesz rekord, ale nie musisz importować klasy rekordu, tak jak podczas korzystania z konstruktora klasy Java.

Więcej szczegółów:

+0

Wielkie dzięki za aktualizację! –

3

Problem jest znany i dużo się o nim mówi na liście mailingowej Clojure. Więcej wsparcia zostanie prawdopodobnie dodane w przyszłych wersjach Clojure.

Teraz trzeba użyć własnych funkcji lub użyć https://github.com/david-mcneil/defrecord2 który obsługuje niektórych funkcji, takich jak:

  • drukiem w eval'able formie
  • zapewniają funkcję Clojure jako konstruktora
  • akceptować parametrów nazwanych (mapy) w konstruktorze
  • udziału w pre/post odległości multi-metoda
6

Foo. jest konstruktorem klasy Java, więc ma typowe ograniczenia między operacjami Java z tym, jak je wywołujesz. Tworzenie funkcji konstruktora jest powszechnym rozwiązaniem (oznacza to również, że nie trzeba importować Foo w innym obszarze nazw).

+0

To jest klasa Java ctor shou Może być szczegółem implementacji? Widziałem, że był to "nowy" defstruct z lepszymi właściwościami wydajności. –

+0

Chciałbym, żeby był to tylko szczegół implementacji, ale tak nie jest (jeszcze). –

+0

Zobacz moją drugą odpowiedź na post-1.3. Natura klasy Java może w dużej mierze zostać teraz zignorowana. –