Reputation: 48729
Clojure, has a declare
macro that allows you to forward-declare functions or variables. It seems to function exactly as def
: Both (declare x)
and (def x)
create #<Unbound Unbound: #'user/x>
When should (declare x)
be used instead of (def x)
?
Upvotes: 23
Views: 1713
Reputation: 3853
def
always applies to the root binding, even if the var is thread-bound at the point where def
is called.
def
yields the var itself (not its value). Throws an exception if symbol is already in the namespace and not mapped to an interned var.
Declare def
s the supplied var names with no bindings, useful for making forward declarations.
Upvotes: 1
Reputation: 12983
The documentation gives the answer:
=> (doc declare)
-------------------------
clojure.core/declare
([& names])
Macro
defs the supplied var names with no bindings, useful for making forward declarations.
Looking at the implementation, it's clear that declare
is defined in terms of def
and provides a little bit of syntax sugar. So functionally, they're pretty much the same.
The advantage of declare
is to show intent for a later reader. (declare x y z)
means I intended to make a forward declaration of those symbols, because the macro is useful for making forward declarations.
(def x) (def y) (def z)
means I'm interning these symbols, but you don't know if I meant to give them definitions and forgot to or whether I'm making forward declarations, or maybe something else subtle.
So, (declare x)
should be preferred over (def x)
when you're making a forward declaration, to show mercy on future readers of your code.
Upvotes: 6
Reputation: 48729
Both declare
and def
do create an unbound var, but there are 3 advantages to using declare
:
(declare x y z)
{:declared true}
declare
is arguably more clear and idiomatic(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)))
Upvotes: 26