Рекомендованные макросы для добавления функциональности в конструктор defrecord Clojure? - PullRequest
12 голосов
/ 04 октября 2010

defrecord в clojure позволяет определять простые контейнеры данных с пользовательскими полями.

например,

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

Минимальный получаемый конструктор принимает только позиционные аргументы без дополнительных функций, таких как дефолтполей, валидация полей и т. д.

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}

Всегда можно написать функции, обертывающие конструктор по умолчанию, чтобы получить более сложную семантику построения - используя аргументы ключевых слов, задавая значения по умолчанию и так далее.

Это кажется идеальным сценарием для макроса для обеспечения расширенной семантики.Какие макросы написали и / или рекомендовали люди для более богатой конструкции defrecord?

Ответы [ 3 ]

9 голосов
/ 04 октября 2010

Примеры поддержки функций конструктора полных и частичных записей и поддержка печатных и печатных форм с возможностью оценки:

Дэвид - мой коллега, и мы широко используем этот defrecord2 в нашем проекте. Я думаю, что-то вроде этого действительно должно быть частью ядра Clojure (конечно, детали могут значительно отличаться).

Вещи, которые мы считаем важными:

  • Возможность создания записи с именованными (возможно частичными) параметрами: (new-foo {: a 1})
  • Возможность создания записи путем копирования существующей записи и внесения изменений: (new-foo old-foo {: a 10})
  • Проверка поля - если вы пропустите поле за пределами объявленных полей записи, выведите ошибку. Конечно, это на самом деле законно и потенциально полезно, поэтому есть способы сделать его необязательным. Поскольку это редко встречается в нашем использовании, гораздо вероятнее будет ошибка.
  • Значения по умолчанию - это было бы очень полезно, но мы не реализовали это. Час Emerick написал о добавлении поддержки значений по умолчанию здесь: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
  • Поддержка печати и печати - мы считаем очень полезным, чтобы записи и печать печатались в форме, которая была бы доступной для возврата к исходной записи. Например, это позволяет запустить тест, провести фактический вывод, проверить его и использовать в качестве ожидаемого результата. Или сильно ударить вывод из отладочной трассировки и получить реальную форму.
4 голосов
/ 04 октября 2010

Вот один , который определяет запись со значениями по умолчанию и инвариантами.Он создает ctor, который может принимать аргументы ключевых слов для установки значений полей.

(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}

И, как я уже сказал ... инварианты:

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

Но они имеют смысл только вконтекст Trammel .

2 голосов
/ 04 октября 2010
...