Reputation: 17650
How can I test wether a variable has been declared or assigned (i.e. check if "a" is defined, when I expect a program to call some code like this (def a (create-a)) ?
And related --- how does the answer to this question relate to the problem of resolving a symbol (i.e. a function) which has been declared ? Clojure: determine if a function exists
It seems like a defined variable should be checkable in the same sense that a defined function is, but I'm finding that the solution for determining if a function exists is not sufficient for determining wether a variable exists.
Some context : I'm writing unit tests for a multideveloper project, and want to make sure that the test data, and the methods in different classes have been defined. Since there is no good IDE support for clojure, it seems to me that, given its loose structure, it is good to test method names and variable names existence before testing their outputs / content.
Upvotes: 13
Views: 4116
Reputation: 92147
Since there is no good IDE support for clojure it seems to me that, given its loose structure, it is good to test method names and variable names existence before testing their outputs / content.
This is nuts. You really want a test to say "Oops! You forgot to define foobar
!" instead of just trying to run foobar
and seeing Clojure's "Unable to resolve symbol" message?
What do you gain from this? You lose the stacktrace, which could be useful if, for example, the test is passed the wrong function name by some other code. Much better to know what line mis-spelled foobar than to search through your whole test namespace.
Upvotes: 1
Reputation: 7825
As others have said, resolve
will return the var for a symbol if there is one defined, or nil. Further, you can check if the var has a value bound to it by using bound?
.
user=> (resolve 'foo) nil user=> (def foo) #'user/foo user=> (resolve 'foo) #'user/foo user=> (bound? #'foo) false user=> (def foo 5) #'user/foo user=> (bound? #'foo) true
Upvotes: 4
Reputation: 8182
One way to do this is to use ns-resolve, for example:
user=> (def a "hello a")
user=> (ns-resolve *ns* 'a)
#'user/a
user=> (ns-resolve *ns* 'b)
;nil ; This assumes b hasn't been defined before...
Note that if you namespace-qualify the symbol to be checked then what you pass as first argument (*ns*
in the example above) doesn't matter:
user=> (ns-resolve 'user 'a)
#'user/a
user=> (ns-resolve 'other 'a)
nil
user=> (ns-resolve 'other 'user/a)
#'user/a
The resolve function mentioned by @tolitius is actually a shorthand for ns-resolve
where the namespace argument always evaluates to ns, depending on the use case it might be more handy.
Upvotes: 4