`def` vs` declare` для форвардной декларации

Clojure, имеет макрос declare, который позволяет вам пересылать функции или переменные. Кажется, он функционирует точно как def: Оба (declare x) и (def x) создают #<Unbound Unbound: #'user/x>

Когда следует использовать (declare x) вместо (def x)?

Ответы

Ответ 1

Оба declare и def действительно создают несвязанный var, но есть 3 преимущества использования declare:

  • Вы можете создать несколько варов в одном выражении, например. (declare x y z)
  • Классы отмечены дополнительными метаданными {:declared true}
  • Использование слова declare возможно более ясное и идиоматическое

(source declare):

(defmacro declare
  "defs the supplied var names with no bindings, useful for making forward declarations."
  {:added "1.0"}
  [& names] `(do [email protected](map #(list 'def (vary-meta % assoc :declared true)) names)))

Ответ 2

В документации дается ответ:

=> (doc declare)
-------------------------
clojure.core/declare
([& names])
Macro
  defs the supplied var names with no bindings, useful for making forward declarations.

Рассматривая реализацию, ясно, что declare определяется в терминах def и предоставляет немного синтаксического сахара. Так функционально, они почти одинаковы.

Преимущество declare - показать намерение для более позднего читателя. (declare x y z) означает, что я намеревался сделать повторное объявление этих символов, потому что макрос useful for making forward declarations.

(def x) (def y) (def z) означает, что я интернирую эти символы, но вы не знаете, намерен ли я давать им определения и забывать, или делаю ли я декларации вперед или, может быть, что-то еще тонкое.

Итак, (declare x) должно быть предпочтительнее, чем (def x), когда вы делаете объявление вперед, чтобы проявить милосердие к будущим читателям вашего кода.

Ответ 3

def всегда применяется к привязке к корню, даже если var связан с потоком в точке, где вызывается def.

def дает сам var (а не его значение). Выдает исключение, если символ уже находится в пространстве имен и не сопоставляется с интернированным var.

Объявить def предоставленные имена переменных без привязок, полезных для внесения деклараций вперед.