在命名空间中,我定义了两个vars(以及其他)是map:
(declare bar)
(def foo {:is-related-to bar})
(def bar {:is-related-to foo})
Run Code Online (Sandbox Code Playgroud)
因为bar我定义时不存在foo,所以我正在使用它进行声明(declare bar).
到目前为止没有问题,一切都在REPL中按预期工作.
我们唯一注意到的是,当我检查fooREPL时,我发现它bar是未绑定的,我认为可以通过以下方式使用declare:
#<Unbound Unbound: #'user/bar>
Run Code Online (Sandbox Code Playgroud)
当我尝试用lein jar或编译软件时出现问题lein ring war(因为它是一个Ring应用程序).我从编译器得到的错误是:
Exception in thread "main" java.lang.RuntimeException: Can't embed object in code, maybe print-dup not defined: Unbound: #'user/bar, compiling...
Run Code Online (Sandbox Code Playgroud)
我认为这也是预料之中的,因为我认为编译器不能处理未绑定的变量.
在任何情况下,如果要预期所有这些行为,如果无法编译,为什么人们使用前向声明?我可能在这里遗漏了一些东西.
您不能以这种方式构造循环引用.它不起作用的原因是因为def计算作为绑定传递的表单,并且评估解析为Var的符号获取该Var的当前绑定.换句话说,有什么获得放入地图foo不是引用到变量bar,它的价值的bar.bar在事实之后重新定义不会影响fooClojure的不可变性.
前向声明通常用于允许函数之间的循环依赖.以下是有效的,因为在实际调用函数之前不会对函数体进行求值; 当定义函数时,它确实是对已编译的Var的引用.
(declare bar)
(defn foo [x y]
(bar x (* 2 y)))
(defn bar
([x] (foo x 3))
([x y] (+ x y)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |