是否有任何宏(声明除外)用于编写函数而不考虑Clojure中函数声明的顺序

时间:2016-06-20 12:50:34

标签: clojure clojurescript

我想在不考虑函数声明顺序的情况下编写函数,我不想使用声明函数,因为我需要声明所有函数名称,我不会这样做想要做到这一点。

我想要一些宏或一些能为我带来魔力的功能。长话短说,我需要编写像Java这样的函数(方法声明顺序重要)

2 个答案:

答案 0 :(得分:5)

我最喜欢函数式编程的一个好处是,它的写作流程与思维流程相同。这就像剥洋葱一样,每时每刻,我只需要专注于这个单层的工作,并将内部部分视为理所当然。并且不用担心函数名称,foobar一开始就没问题。在这种写作风格中,函数从源文件的末尾定义并实现回顶部。在一个函数调用多个其他函数的情况下,此线性结构变为树状结构,但文件中始终存在单个点以插入新函数。没有选择和担忧。

是的,有时候我们需要处理一些没有其他依赖关系的代码片段。当然,它们可以放在源文件的顶部。

要提前回答这个问题,macros并非神奇。如果存在这样的宏,则该宏将需要将整个源文件作为输入,分析每个代码块之间的依赖关系,并以正确的顺序重新流动它们。由于词汇范围的存在,对依赖性的分析是非平凡的。它几乎就像编写编译器一样。我不相信这样的宏存在(已由任何人编写),它能做的商品对我来说不是那么大。

答案 1 :(得分:2)

这是一种不必要的,但很容易作为练习(直到某一点)。您可以编写宏,它将转发声明包含在其中的所有顶级函数:

(defmacro with-forward-declaration [& body]              
  (let [names (keep #(when (#{'defn 'defn-} (first %))
                       (if (map? (second %)) (nth % 2) (second %)))
                    body)]
    `(do (declare ~@names)
         ~@body)))

它是如何扩展的:

(with-forward-declaration

  (defn ^long ff1 [x] (* 2 (ff2)))

  (println "just to be sure it doesn't eat other forms")

  (defn ^{:name 'xx} ff2 [] (+ 10 (ff3)))

  (defn ff3 [] 101)

  (defn- ff4 [] :x))

会执行以下操作:

(do
  (declare ff1 ff2 ff3 ff4)
  (defn ff1 [x] (* 2 (ff2)))
  (println "just to be sure it doesn't eat other forms")
  (defn ff2 [] (+ 10 (ff3)))
  (defn ff3 [] 101)
  (defn- ff4 [] :x))

因此,如果您将所有命名空间的代码包装到此宏中,它将为您预先声明所有函数。如果你想要更深入,比如预先设置不在顶级的所有可能的defn,你可以使用clojure.walk更新这个玩具宏来找到这些内部形式..但我猜这个一个是足够的,快速玩clojure,而不考虑功能'订购。我不会在生产中这样做(至少没有经过严格的测试)。