Рекомендуемые макросы для добавления функциональности в конструктор дезаписи Clojure?

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

e.g.

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 построения?


person Alex Stoddard    schedule 04.10.2010    source источник
comment
Я должен отметить, что дезапись имеет гораздо большее значение с точки зрения того, как она работает с экосистемой Clojure/Java, простые контейнеры данных, описанные выше, вовсе не означают рудиментарность, как раз наоборот.   -  person Alex Stoddard    schedule 06.10.2010
comment
Следует отметить, что начиная с clojure 1.3.0 вы можете делать (map->Book {:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657) или #user.Book{:author "J.R.R Tolkien", :title "The Lord of the Rings", :ISBN 9780618517657}   -  person Claude    schedule 27.03.2012
comment
Документацию по функциям, отмеченным Клодом, см. по адресу: dev.clojure.org/display/design/ отсрочка записи+улучшения   -  person Alex Stoddard    schedule 05.09.2012


Ответы (3)


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

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

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

  • Возможность создания записи с именованными (возможно частичными) параметрами: (new-foo {:a 1})
  • Возможность создания записи путем копирования существующей записи и внесения изменений: (new-foo old-foo {:a 10})
  • Проверка поля - если вы передаете поле вне объявленных полей записи, выдает ошибку. Конечно, на самом деле это законно и потенциально полезно, поэтому есть способы сделать это необязательным. Поскольку это было бы редко в нашем использовании, гораздо более вероятно, что это ошибка.
  • Значения по умолчанию — они были бы очень полезны, но мы их не реализовали. Час Эмерик написал о добавлении поддержки значений по умолчанию здесь: http://cemerick.com/2010/08/02/defrecord-slot-defaults/
  • Поддержка печати и печати — мы считаем очень полезным иметь записи для печати и печати в форме, которая может быть возвращена к исходной записи. Например, это позволяет вам запустить тест, просмотреть фактический результат, проверить его и использовать в качестве ожидаемого результата. Или смахнуть вывод из трассировки отладки и получить реальную форму для оценки.
person Alex Miller    schedule 04.10.2010
comment
Определенно согласен с тем, что неопределенное поле, вероятно, является ошибкой (но полезно, когда преднамеренно). Поскольку, по-видимому, известно, что поле расширения является преднамеренным, возможно, оно должно иметь другую функцию, и прямая связь выдает ошибку. Мне также интересно, будут ли полезны метаданные в расширенной записи. - person Alex Stoddard; 04.10.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.

person fogus    schedule 04.10.2010

Вот один из подходов: http://david-mcneil.com/post/765563763/enhanced-clojure-records

person Ben Mabey    schedule 04.10.2010