Подтвердить что ты не робот

Где я должен использовать defrecord в clojure?

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

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

Ответ 4

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

Ответ 5

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

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