【问题标题】:Is there any macro(except declare) for writing functions without think of the order of function declarations in Clojure是否有任何宏(除了声明)用于编写函数而不考虑 Clojure 中函数声明的顺序
【发布时间】:2016-06-21 15:55:21
【问题描述】:

我想编写函数而不考虑函数声明的顺序,我不想使用 declare 函数,因为我需要声明所有我不想这样做的函数名.

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

【问题讨论】:

    标签: clojure clojurescript


    【解决方案1】:

    我最喜欢函数式编程的最好的一点是,它的写作流程与思维流程相同。就像剥洋葱一样,每时每刻,我只需要集中精力在这一层上,把里面的部分视为理所当然。并且不要担心函数名称,foobar 一开始会很好。在这种写作风格中,函数是从源文件的末尾到顶部定义和实现的。在一个函数调用多个其他函数的情况下,这种线性结构变成了树状结构,但文件中总是有一个点可以插入新函数。没有选择和担忧。

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

    要提前回答这个问题,macros 并不神奇。如果存在这样的宏,则该宏需要将整个源文件作为输入,分析每个代码块之间的依赖关系,并以正确的顺序重新排列它们。由于词法作用域,依赖关系的分析很重要。这几乎就像编写一个编译器。我不相信这样的宏存在(任何人都写过),它可以做的事情对我来说不是那么大。

    【讨论】:

      【解决方案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))
      

      因此,如果您将所有命名空间的代码包装到此宏中,它将为您预先声明所有函数。如果你想更深入一点,比如预先声明所有可能的defns 不在顶层,你可以使用clojure.walk 更新这个玩具宏来找到这些内部形式。但我想这个就足够了, 快速使用 clojure,无需考虑函数的顺序。不过,我不会在生产中这样做(至少在没有大量测试的情况下不会这样做)。

      【讨论】:

      • 这个宏也不灵活,因为它不适用于原始的def 表单或扩展为defndefn- 表单的其他宏。
      • 显然。我只是想表明这是可能的。其余的取决于实施者。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 2018-10-26
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      • 2021-09-19
      相关资源
      最近更新 更多