clojure forward-declaration

clojure - `def` vs` declare` para declaración hacia adelante



forward-declaration (3)

Clojure, tiene una macro de declare que le permite reenviar y declarar funciones o variables. Parece funcionar exactamente como def : Both (declare x) y (def x) create #<Unbound Unbound: #''user/x>

¿Cuándo debería usarse (declare x) lugar de (def x) ?


La documentación da la respuesta:

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

En cuanto a la implementación , está claro que declare se define en términos de def y proporciona un poco de sintaxis de azúcar. Así que funcionalmente, son casi lo mismo.

La ventaja de declare es mostrar intención para un lector posterior. (declare xyz) significa que tenía la intención de hacer una declaración hacia adelante de esos símbolos, porque la macro es useful for making forward declarations.

(def x) (def y) (def z) significa que estoy internando estos símbolos, pero no sabes si quise darles definiciones y olvidé o si estoy haciendo declaraciones hacia adelante, o tal vez algo más sutil .

Por lo tanto, (declare x) debe preferirse a (def x) cuando realice una declaración hacia adelante, para mostrar clemencia a los futuros lectores de su código.


Tanto declare como def crean una var. No vinculada, pero hay 3 ventajas al usar declare :

  1. Puede crear múltiples vars en una declaración, por ejemplo, (declare xyz)
  2. Las variables están etiquetadas con los metadatos adicionales {:declared true}
  3. Usar la palabra declare es posiblemente más claro e idiomático

(source declare) :

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


def siempre se aplica al enlace de raíz, incluso si la var está enlazada a un hilo en el punto donde se llama def .

def produce la var en sí (no su valor). Lanza una excepción si el símbolo ya está en el espacio de nombres y no está asignado a una var internada.

Declare def s los nombres de var suministrados sin enlaces, útil para hacer declaraciones a futuro.