【问题标题】:Are Clojure macros always leaky?Clojure 宏总是泄漏的吗?
【发布时间】:2012-05-25 16:01:27
【问题描述】:

如果您阅读问题macro -> with anonymous functions,您会发现-> 宏不适用于匿名函数。要正确使用宏,您需要了解实现。从这个意义上说,宏是“有漏洞的”——API 并未完全隐藏实现。

(足够复杂的)Clojure 宏是否总是存在漏洞?

[比较:C 预处理器也会出现类似的问题,如果不小心处理宏参数,会出现奇怪的副作用。在这种情况下,可以通过将宏参数括在括号中(在宏内部)来解决问题。这并不能解决使用具有可变状态的 C 宏(即每次使用参数都会改变状态)的问题,但也许我们可以忽略函数式语言的这个问题,或者使用 let 来避免多次评估。]

【问题讨论】:

    标签: macros clojure


    【解决方案1】:

    您不需要了解实现 - 文档字符串非常清楚它是如何工作的。阅读器宏也有据可查 - #(...) 将扩展为 (fn [..] ...)。鉴于这些知识和提供的文档字符串信息,很明显线程匿名函数将不起作用。完全不需要了解实现。

    【讨论】:

      【解决方案2】:

      从这个意义上说,Clojure 宏并没有泄漏。原因 -> 使用 #() 函数出人意料的是,#() 是一个阅读器宏,阅读器宏在“常规”宏之前展开。所以你需要知道:

      1. 宏应该做什么。 -> 实际上是一个非常基本的宏,因为文档几乎准确地解释了它是如何扩展的。
      2. 如果您想将读取器宏传递给“普通”宏,它会扩展成什么。

      【讨论】:

        【解决方案3】:

        另请注意,如果您将匿名函数包装在括号中,它将起作用:

        => (-> {:a 1 :b 2} :a (#(* 2 %)))
        2
        

        写出匿名函数然后对其进行宏扩展很有启发性:

        => (-> {:a 1 :b 2} :a ((fn [el] (* 2 el))))
        2
        

        和

        => (macroexpand-all '(-> {:a 1 :b 2} :a ((fn [el] (* 2 el)))))
        ((fn* ([el] (* 2 el))) (:a {:a 1, :b 2}))
        

        【讨论】:

          猜你喜欢
          • 2011-10-11
          • 2020-04-12
          • 1970-01-01
          • 2019-04-02
          • 2020-07-01
          • 1970-01-01
          • 2011-02-20
          • 2013-08-12
          相关资源
          最近更新 更多