首页 文章

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

提问于
浏览
1

我是Clojure的新手,我只想尝试构建一些示例应用程序以熟悉语法 . 我注意到以下顺序依赖行为 .

我创建了一个名为timex的项目来计算两个日期之间的周数 . 我正在使用clj-time函数进行日期差异计算 .

如果我的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!"

这种明显的顺序依赖正常还是我做错了什么?如果是后者,那么我将不胜感激任何我应该审查的建议或文件 . 谢谢 .

1 回答

  • 3

    Clojure中的编译单元是 s-expression ,而不是像许多其他语言一样的整个文件 . 加载文件 file is evaluated from top to bottom in a single pass 的文件时 . vars(通过调用 def 创建的内容)必须在它们使用的位置上方创建,或者如果需要相互递归,则可以使用 declare ,尽管这种情况很少见 .

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

    PS:绝大部分时间对 require 的调用都是在文件顶部的 ns 表单中 .

相关问题