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
:
- Puede crear múltiples vars en una declaración, por ejemplo,
(declare xyz)
- Las variables están etiquetadas con los metadatos adicionales
{:declared true}
- 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.