2015-11-22 2 views
15

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

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

ответ

17

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

  1. Вы можете создать несколько ВАР в одном операторе, например, (declare x y z)
  2. В вары помечаются с дополнительными метаданными {:declared true}
  3. Используя слово 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))) 
3

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

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

Looking at the implementation, ясно, что declare определяется в терминах def и содержит немного синтаксиса сахара. Так функционально, они почти одинаковы.

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

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

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

1

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

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

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