Clojure:如果在源代码中定义之前调用函数,为什么函数应该是`declare`

时间:2015-10-15 08:49:57

标签: clojure

在Clojure中,如果你在定义之前调用一个函数,例如

(foo (bar 'a))

(defn bar [] ...)

它没有编译。应该添加

(declare bar)
(foo (bar 'a))之前

。为什么Clojure是这样设计的?我的意思是,在大多数语言中,除了C / C ++,如Java,Python,PHP,Scala,Haskell甚至其他Lisps,特别是在动态类型语言中,不需要函数声明,也就是说,函数定义可以放在在通话之前或之后。我觉得使用起来很不舒服。

1 个答案:

答案 0 :(得分:15)

Clojure进行单遍编译(我简化,阅读以下链接):

因此,如果您只阅读一次源代码,从上到下,您就不能像前向声明那样安全地执行此操作,这似乎是合乎逻辑的。

引用Rich(第一个链接):

  

但是,这里应该发生什么,当编译器从未见过时   酒吧?

`(defn foo [] (bar))`
     

或在CL:

`(defun foo () (bar))`
     

CL很乐意编译它,如果从未定义bar,则会发生运行时错误。好的,但是,什么具体化的东西   (符号)在编译期间是否用于栏?它实施的符号   当表格被阅读。那么,当你获得运行时会发生什么   错误并意识到bar是在您忘记的另一个包中定义的   进口。你试图导入其他包和BAM !,另一个错误 -   冲突,其他包:bar与read-in-package冲突:bar。然后   你去学习uninterning。

     

在Clojure中,表单没有编译,   你得到一条消息,并没有实际的条形码。你需要   其他命名空间并继续。

     

我非常喜欢这种经历,等等   做出了这些权衡。使用a带来许多其他好处   非实习读者,仅在定义/声明上实习。   我不倾向于放弃它们,也没有提到前面提到的好处,   为了支持循环参考。

相关问题