我想在不考虑函数声明顺序的情况下编写函数,我不想使用声明函数,因为我需要声明所有函数名称,我不会这样做想要做到这一点。
我想要一些宏或一些能为我带来魔力的功能。长话短说,我需要编写像Java这样的函数(方法声明顺序不重要)
答案 0 :(得分:5)
我最喜欢函数式编程的一个好处是,它的写作流程与思维流程相同。这就像剥洋葱一样,每时每刻,我只需要专注于这个单层的工作,并将内部部分视为理所当然。并且不用担心函数名称,foo
和bar
一开始就没问题。在这种写作风格中,函数从源文件的末尾定义并实现回顶部。在一个函数调用多个其他函数的情况下,此线性结构变为树状结构,但文件中始终存在单个点以插入新函数。没有选择和担忧。
是的,有时候我们需要处理一些没有其他依赖关系的代码片段。当然,它们可以放在源文件的顶部。
要提前回答这个问题,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,而不考虑功能'订购。我不会在生产中这样做(至少没有经过严格的测试)。