Где я должен использовать defrecord в clojure? - PullRequest
69 голосов
/ 01 января 2011

Я использую много карт и структур в моих программах clojure.Каковы преимущества (помимо производительности) их преобразования в списки?

Ответы [ 5 ]

87 голосов
/ 02 января 2011

Я считаю структуры устаревшими, поэтому я их вообще не использую.

Когда у меня есть фиксированный набор хорошо известных ключей, используемых во многих экземплярах карты, я обычно создаю запись.Большие преимущества:

  • Производительность
  • Сгенерированный класс имеет тип, который я могу включить в мультиметодах или в других ситуациях
  • С дополнительными макро-механизмами вокруг defrecord, яможет получить проверку поля, значения по умолчанию и все, что я хочу
  • Записи могут реализовывать произвольные интерфейсы или протоколы (карты не могут)
  • Записи действуют как карты для большинства целей
  • ключи и значения возвращают результаты в стабильном (на создание) порядке

Некоторые недостатки записей:

  • Поскольку записи являются экземплярами класса Java (не картами Clojure),нет структурного совместного использования, поэтому та же самая структура записи, вероятно, будет использовать больше памяти, чем эквивалентная структура карты, которая была изменена.Существует также больше создания / уничтожения объектов по мере того, как вы «меняете» запись, хотя JVM специально разработана для того, чтобы есть этот вид недолговечного мусора, не потревожив.
  • Если вы меняете записи во время разработки, вы, вероятно,нужно чаще перезапускать ваш REPL, чтобы подобрать эти изменения.Обычно это проблема только в узких местах разработки.
  • Многие существующие библиотеки не были обновлены для поддержки записей (postwalk, zip, matchure и т. Д. И т. Д.).Мы добавили эту поддержку по мере необходимости.
14 голосов
/ 03 января 2011

Стюарт Сьерра недавно написал интересную статью «Решение проблемы выражения с Clojure 1.2», в которой также есть раздел, посвященный defrecord:

http://www.ibm.com/developerworks/java/library/j-clojure-protocols/index.html#datatypes

Я думаю, что вся статья является хорошей отправной точкой для понимания протоколов и записей.

9 голосов
/ 02 января 2011

Еще одно важное преимущество заключается в том, что запись имеет тип (свой класс), с которого вы можете отправлять сообщения.

Примером, использующим эту функцию, но не представляющим все возможные варианты использования, является следующее:

(defprotocol communicate
  (verbalize [this]))

(defrecord Cat [hunger-level]
  communicate
  (verbalize [this]
    (apply str (interpose " " (repeat hunger-level "meow")))))

(defrecord Dog [mood]
  communicate
  (verbalize [this]
    (case mood
      :happy "woof"
      "arf")))

(verbalize (->Cat 3))
; => "meow meow meow"

(verbalize (->Dog :happy))
; => "woof"
2 голосов
/ 20 октября 2015

Используйте карты в большинстве случаев и записи только тогда, когда вам требуется полиморфизм. С одними картами вы все еще можете использовать мультиметоды; однако вам нужны записи, если вы хотите протоколы. Учитывая это, подождите, пока вам не понадобятся протоколы, прежде чем прибегать к записям. До тех пор избегайте их в пользу более ориентированного на данные и более простого кода.

0 голосов
/ 20 мая 2017

В дополнение к тому, что было отмечено ранее, помимо того, что он, как правило, находится на одном уровне или выше с точки зрения производительности и предоставляет тот же интерфейс программирования, что и карта, записи обеспечивают мягкую структуру: имена ключей и количество ключей применяются при время определения. Это может быть полезно во избежание глупых ошибок, когда одна и та же структура ожидается от многих значений (или просто искусственно жесткая в противном случае).

Какими бы ни были исходные мотивы, это свойство также отличает его от карт.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...