Каковы некоторые виды использования метаданных Clojure?

#clojure #metadata

#функциональное программирование #clojure #метаданные

Вопрос:

Как вы использовали метаданные в своей программе Clojure?

Я видел один пример из программирования Clojure:

 (defn shout [#^{:tag String} message] (.toUpperCase message))
;; Clojure casts message to String and then calls the method.
  

Каковы некоторые виды использования? Эта форма программирования совершенно новая для меня.

Ответ №1:

  • Строки документации хранятся в виде метаданных под ключом :doc. Вероятно, это наиболее очевидное использование метаданных номер 1.
  • Типы возвращаемых данных и параметров могут быть дополнительно помечены метаданными, чтобы повысить производительность, избегая накладных расходов на анализ типов во время выполнения. Они также известны как «подсказки по типу». #^String это подсказка по типу.
  • Хранение вещей «под капотом» для использования компилятором, таких как список аргументов функции, номер строки, в которой был определен var, или содержит ли var ссылку на макрос. Обычно они автоматически добавляются компилятором, и пользователю обычно не нужно управлять ими напрямую.
  • Создание простых тестовых наборов как части определения функции:

    (defn #^{:test (fn [] (assert true))} something [] nil)

    (test #'something)

Если вы читаете Programming Clojure, то глава 2 содержит хорошее введение в метаданные. На рисунке 2.3 представлено хорошее резюме общих метаданных.

Ответ №2:

Для разнообразия какой-нибудь ответ, который не концентрируется на взаимодействии с самим языком:

Вы также можете, например. отслеживать источник некоторых данных. Непроверенный ввод помечен как :tainted . Средство проверки может что-то проверить, а затем установить статус на :clean . Код, выполняющий действия, связанные с безопасностью, может затем отключиться :tainted и принимать :clean только отредактированный ввод.

Ответ №3:

Метаданные были чрезвычайно полезны для меня при наборе текста. Я говорю не только о подсказках по типу, но и о полной пользовательской системе типов. Простейший пример — перегрузка print-метода для structs (или любого другого var):

 (defstruct my-struct :foo :bar :baz)

(defn make-my-struct [foo bar baz]
   (with-meta (struct-map my-struct :foo foo :bar baz :baz baz)
      {:type ::my-struct}))


(defmethod print-method 
   [my-struct writer]
   (print-method ...))
  

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

Дополнительные идеи по набору текста см. в разделе types-api.

Ответ №4:

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

 (defn foo [ #^String stringy] ....
  

Я использовал его для таких вещей, как хранение количества отступов, добавленных к числу. Он предназначен для информации, которая «ортогональна» данным и не должна учитываться при принятии решения о том, совпадают ли ваши значения.