Clojure:resolve声明符号

时间:2012-01-14 12:51:22

标签: clojure symbols resolve declare

检查符号是否可以解析时,我会遇到一些奇怪的行为。

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

谁能告诉我这可能来自哪里?这种行为是否打算?

2 个答案:

答案 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在引用的表单中并在解析后进行评估。