在-main中调用函数时的Clojure顺序依赖关系

在-main中调用函数时的Clojure顺序依赖关系,clojure,Clojure,我是Clojure的新手,正在尝试构建一些示例应用程序来适应语法。我注意到以下顺序依赖行为 我创建了一个名为timex的项目来计算两个日期之间的时间(以周为单位)。我使用clj时间函数计算日期差 如果my core.clj如下所示: (ns timex.core (:gen-class)) (defn -main "Calculate weeks between dates." [& args] dp ) (require '[clj-time.core :a

我是Clojure的新手,正在尝试构建一些示例应用程序来适应语法。我注意到以下顺序依赖行为

我创建了一个名为timex的项目来计算两个日期之间的时间(以周为单位)。我使用clj时间函数计算日期差

如果my core.clj如下所示:

 (ns timex.core
  (:gen-class))
 (defn -main
  "Calculate weeks between dates."
  [& args]
  dp
   )
 (require '[clj-time.core :as t])
 (def d2 (t/date-time 1989 01 07))
 (def dw (t/in-weeks (t/interval d2 (t/now))))
 (def dp (str "The number of weeks between Jan 7, 1989 and now is " dw "!"))
**

如果运行lein repl,则会出现以下错误: #CompilerException java.lang.RuntimeException:无法解析此上下文中的符号:dp,正在编译:(timex/core.clj:4:1)

但是如果我重新排列文件中的行,并将def和require语句放在main之前,那么

(ns timex.core
  (:gen-class))
 (require '[clj-time.core :as t])
 (def d2 (t/date-time 1989 01 07))
 (def dw (t/in-weeks (t/interval d2 (t/now))))
 (def dp (str "The number of weeks between Jan 7, 1989 and now is " dw "!"))
 (defn -main
  "Calculate weeks between dates."
  [& args]
  dp
   )
**

然后,当我运行lein repl并调用(-main)函数时,我得到:

timex.core=> (-main)

"The number of weeks between Jan 7, 1989 and now is 1341!"

这种明显的订单依赖是正常的还是我做错了什么?如果是后者,那么我将非常感谢任何我应该审查的建议或文件。谢谢。

Clojure中的编译单元是
s-expression
,而不像许多其他语言那样是一个完整的文件。加载文件时,将在一次过程中从上到下对该文件进行评估。变量(通过调用
def
创建的)必须在使用它们的位置上方创建,或者如果需要相互递归,可以使用
declare
,尽管这种情况很少

花一些时间来习惯传统意义上的编译文件和lisp意义上的加载文件之间的区别是值得的,因为它是宏系统和语言的许多其他方面的基础。当您需要命名空间中的文件,或从repl调用
load file
时,将调用clojure编译器并重复读取,宏将展开,然后从顶部开始计算文件中的每个文件。第一行告诉它定义事物的名称空间,这就是为什么
ns
表达式首先出现的原因。然后,进一步的表单定义该名称空间中的内容。如果再次加载文件,它只不过是从顶部重新读取文件而已。它不会清除名称空间或任何其他魔法,因此,如果您对文件求值,然后更改顺序并再次求值,它可以继续工作,因为在运行第二个过程时,所需的函数已经在名称空间中定义(存储在memeory中)。习惯了这一点后,经常运行
lein check
,以确保事情井然有序

注:对
require
的调用绝大多数时间都是在文件顶部的
ns
表单中进行的。

有一篇文章讨论了与编译单元相关的设计思想。