简体   繁体   English

Clojure宏总是漏水吗?

[英]Are Clojure macros always leaky?

If you read the question macro -> with anonymous functions you'll see that the -> macro doesn't play well with anonymous functions. 如果您阅读问题宏 - >使用匿名函数,您将看到->宏与匿名函数不兼容。 To use the macro correctly you need to understand the implementation . 要正确使用宏,您需要了解实现 In that sense, the macro is "leaky" - the implementation is not completely hidden by the API. 从这个意义上说,宏是“漏洞” - API没有完全隐藏实现。

Is it always that case that a (sufficiently complex) Clojure macro is leaky? (足够复杂的)Clojure宏是否会泄漏?

[For comparison: A similar issue occurs with the C pre-processor, where strange side effects can be seen when macro arguments are handled carelessly. [为了比较:C预处理器出现了类似的问题,当粗略地处理宏参数时,可以看到奇怪的副作用。 In that case, issues can be solved by enclosing the macro arguments in parentheses (inside the macro). 在这种情况下,可以通过将宏参数括在括号中(宏内部)来解决问题。 That does not solve the issue of using C macros with mutable state (ie where each use of the argument mutates state), but perhaps we can either ignore that issue for functional languages, or use let to avoid multiple evaluations.] 这并没有解决使用具有可变状态的C宏的问题(即每次使用参数都会改变状态),但也许我们可以忽略函数式语言的问题,或者使用let来避免多次评估。

You don't need to understand the implementation - the docstring is quite clear as to how it works. 您不需要了解实现 - 文档字符串很清楚它是如何工作的。 Reader macros are also well documented - #(...) will expand to (fn [..] ...). 读者宏也有很好的文档记录 - #(...)将扩展为(fn [...] ...)。 Given this knowledge and the information provided docstring it's clear that threading anonymous functions won't work. 鉴于这些知识和所提供的信息,很明显,线程匿名函数不起作用。 No need to understand the implementation at all. 根本不需要理解实现。

Clojure macros aren't leaky in that sense. 从这个意义上讲,Clojure宏不会泄漏。 The reason -> works sort of unexpectedly with #() functions is that #() is a reader macro and reader macros are expanded before "regular" macros. 原因 - >使用#()函数意外地工作的是#()是一个读取器宏,读取器宏在“常规”宏之前扩展。 So you need to know: 所以你需要知道:

  1. What the macro is supposed to do. 宏应该做什么。 -> is actually a very basic macro in that the documentation pretty much explains exactly how it expands. - >实际上是一个非常基本的宏,因为文档几乎可以解释它是如何扩展的。
  2. What a reader macro expands into if you want to pass it to a "normal" macro. 读取器宏如果要将其传递给“普通”宏,会扩展为什么。

Also note that it will work if you wrap anonymous functions in parens: 另请注意,如果您将匿名函数包装在parens中,它将起作用:

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

Writing out the anonymous function and then macroexpanding it is illuminating: 写出匿名函数,然后宏扩展它是有启发性的:

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

and

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM