Vraag Aanbevolen macro's om functionaliteit toe te voegen aan Clojure's defrecord constructor?


defrecord in clojure kunnen eenvoudige gegevenscontainers met aangepaste velden worden gedefinieerd.

bijv.

user=> (defrecord Book [author title ISBN])
user.Book

De minimale constructor die resultaten oplevert, neemt alleen positionele argumenten zonder extra functionaliteit zoals het in gebreke blijven van velden, veldvalidatie enz.

user=> (Book. "J.R.R Tolkien" "The Lord of the Rings" 9780618517657)
#:user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}

Het is altijd mogelijk om functies te schrijven die de standaardconstructor wikkelen om meer complexe constructiesemantiek te krijgen - met behulp van trefwoordargumenten, het leveren van standaardwaarden, enzovoort.

Dit lijkt het ideale scenario voor een macro om uitgebreide semantiek te bieden. Welke macro's hebben mensen geschreven en / of aanbevolen voor rijker defrecord bouw?


12
2017-10-04 15:32


oorsprong


antwoorden:


Voorbeelden van ondersteuning voor volledige en gedeeltelijke recordconstructorfuncties en ondersteuning voor evalable print- en pprint-formulieren:

David is een collega van mij en we gebruiken dit defrecord2 uitgebreid in ons project. Ik denk dat zoiets echt onderdeel moet zijn van Clojure-kern (details kunnen natuurlijk aanzienlijk verschillen).

De dingen die belangrijk zijn, zijn:

  • Mogelijkheid om een ​​record samen te stellen met benoemde (mogelijk gedeeltelijke) parameters: (new-foo {: a 1})
  • De mogelijkheid om een ​​record te construeren door een bestaand record te kopiëren en wijzigingen aan te brengen: (new-foo old-foo {: a 10})
  • Veldvalidatie - geef een fout als u een veld buiten de gedeclareerde recordvelden doorgeeft. Natuurlijk is dit eigenlijk legaal en potentieel nuttig, dus er zijn manieren om het optioneel te maken. Aangezien dit in ons gebruik zelden voorkomt, is het veel waarschijnlijker dat er een fout optreedt.
  • Standaardwaarden - deze zouden zeer nuttig zijn, maar we hebben het niet geïmplementeerd. Chas Emerick heeft hier geschreven over het toevoegen van ondersteuning voor standaardwaarden: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
  • Print- en pprint-ondersteuning - we vinden het erg handig om records te laten afdrukken en pprinten in een vorm die evalable is naar het oorspronkelijke record. Hiermee kunt u bijvoorbeeld een test uitvoeren, de werkelijke uitvoer vegen, verifiëren en gebruiken als de verwachte uitvoer. Of om uitvoer van een foutopsporingsspoor te vegen en een echt evaliseerbare vorm te krijgen.

9
2017-10-04 16:09



Hier is er een die een record definieert met standaardwaarden en invarianten. Er wordt een ctor gemaakt die zoekwoordargumenten kan gebruiken om de waarden van de velden in te stellen.

(defconstrainedrecord Foo [a 1 b 2]
  [(every? number? [a b])])

(new-Foo)
;=> #user.Foo{:a 1, :b 2}

(new-Foo :a 42)
; #user.Foo{:a 42, :b 2}

En zoals ik al zei ... invarianten:

(new-Foo :a "bad")
; AssertionError

Maar ze zijn alleen logisch in de context van Trammel.


4
2017-10-04 16:22



Hier is een benadering: http://david-mcneil.com/post/765563763/enhanced-clojure-records


2
2017-10-04 16:08