在Clojure中,如果你在定义之前调用一个函数,例如
(foo (bar 'a))
(defn bar [] ...)
它没有编译。应该添加
(declare bar)
在(foo (bar 'a))
之前。为什么Clojure是这样设计的?我的意思是,在大多数语言中,除了C / C ++,如Java,Python,PHP,Scala,Haskell甚至其他Lisps,特别是在动态类型语言中,不需要函数声明,也就是说,函数定义可以放在在通话之前或之后。我觉得使用起来很不舒服。
答案 0 :(得分:15)
Clojure进行单遍编译(我简化,阅读以下链接):
因此,如果您只阅读一次源代码,从上到下,您就不能像前向声明和那样安全地执行此操作,这似乎是合乎逻辑的。
引用Rich(第一个链接):
但是,这里应该发生什么,当编译器从未见过时 酒吧?
`(defn foo [] (bar))`
或在CL:
`(defun foo () (bar))`
CL很乐意编译它,如果从未定义bar,则会发生运行时错误。好的,但是,什么具体化的东西 (符号)在编译期间是否用于栏?它实施的符号 当表格被阅读。那么,当你获得运行时会发生什么 错误并意识到bar是在您忘记的另一个包中定义的 进口。你试图导入其他包和BAM !,另一个错误 - 冲突,其他包:bar与read-in-package冲突:bar。然后 你去学习uninterning。
在Clojure中,表单没有编译, 你得到一条消息,并没有实际的条形码。你需要 其他命名空间并继续。
我非常喜欢这种经历,等等 做出了这些权衡。使用a带来许多其他好处 非实习读者,仅在定义/声明上实习。 我不倾向于放弃它们,也没有提到前面提到的好处, 为了支持循环参考。