检查符号是否可以解析时,我会遇到一些奇怪的行为。
user=> ok
CompilerException java.lang.RuntimeException: Unable to resolve symbol: ok in this context, compiling:(NO_SOURCE_PATH:0)
user=> (resolve 'ok)
nil
user=> (if (resolve 'ok) "bla" (def ok 'ok))
"bla"
user=> ok
#<Unbound Unbound: #'user/ok>
user=> (def ok 'ok)
#'user/ok
user=> ok
ok
谁能告诉我这可能来自哪里?这种行为是否打算?
答案 0 :(得分:4)
(def ok "whatever")
在编译时创建名为ok
的变量。编译器扫描整个表单以编译它,发现您将定义一个名为ok
的var,并在您的表单实际执行之前为您创建它(没有绑定)。实际执行def
表单时,表达式的运行时值将分配给var user/ok
。在您的示例中,这种情况永远不会发生,因为已经创建了var,而if
分支则是另一种方式。
使用bound?
作为替代是一个可怕的想法,因为它测试了一些完全不同的东西:命名var(必须存在)是否具有永久或本地线程的绑定。
答案 1 :(得分:1)
由于我只在宏中使用它,现在使用它如下
(defmacro bla [x]
(if (resolve x) x `(def ~x '~x)))
现在它可以正常工作,因为def在引用的表单中并在解析后进行评估。