在 Clojure 文件中包含多个文件

including multiple files in a Clojure file

我是 Clojure 的新手。我知道有一种方法可以使用像 C++ 的 #include 这样的关键字将文件包含在其他文件中。我做了一些挖掘,发现了一些指向关键字 declare 的东西。也许我没有正确使用它,但它似乎不适合我。

我正在尝试编写一个函数,例如 get_all_preds,它使用另一个函数的前身,写在另一个文件中。这些文件都在目录 src 下,每个函数都是其各自文件中的唯一代码。

当我添加(声明 bar.clj)到 foo.clj 文件的顶部时,我仍然收到无法找到栏的错误。

(defn get_all_preds
 ([tasks job]
   (cond (empty? (predecessors tasks job)) (println "No predecessors")
   :else (get_all_preds tasks (predecessors tasks job) (empty tasks))))
 ([tasks prereqs job]
   (cond (empty? prereqs) job
   :else (get_all_preds tasks (distinct (flatten (concat (predecessors tasks (first prereqs)) (rest prereqs)))) 
 (distinct (cons (first prereqs) job))))))

(defn predecessors
[tasks-list job]
  (cond (empty? tasks-list) 0
  (= job (first (first tasks-list))) (rest (rest (first tasks-list)))
  :else (predecessors (rest tasks-list) job)))

declare 用于创建 var 而不将其绑定到值。

加载另一个 Clojure 命名空间的正确函数是 require。要使用 require,您需要使用命名空间,并创建具有反映文件所含命名空间语义结构的路径的文件。与 #include 最接近的等价物是 load,但这应该保留用于非结构化实验,在这些实验中您不妨复制/粘贴到 repl 中,或者名称空间不合适的异常情况。

一个简单的例子:

在文件 src/foo/bar.clj 中:

(ns foo.bar)

(defn frob [] "hello")

在文件 src/foo/baz.clj 中:

(ns foo.baz
  (:require [foo.bar :as bar]))

(defn frob [] (str (bar/frob) (bar/frob)))

(defn -main [& args]
   (println (frob))

运行 foo.baz/-main 将打印 "hellohello" 后跟一个新行。

Clojure 命名空间是一个比 C 的编译单元更结构化的概念,并且您可以在代码中以细粒度的方式直接与之交互。一开始看起来很奇怪,但它允许细粒度地控制从代码的各个部分可见的定义(这反过来有助于使代码更易于维护和理解)。