首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >宏到宏交互惊喜

宏到宏交互惊喜
EN

Stack Overflow用户
提问于 2018-03-19 22:22:41
回答 1查看 90关注 0票数 0

这个问题与两个宏之间的相互作用有关,一个宏包含在另一个宏中。所描述的两个宏是说明交互作用的例子,而不是唯一的例子。

考虑一个简单的clojure宏,它会产生副作用,但在其他情况下将其输入传递不变。

代码语言:javascript
复制
(defmacro echo [action & args]
  `(fn [tru#] (do (~action ~@args tru#) tru#)))

用法

代码语言:javascript
复制
((echo log/info "result") :foo)

将该宏包含在另一个宏中,例如->>宏。我的直觉是这样做的:

代码语言:javascript
复制
(->> :foo (echo log/info "result") clojure.pprint/pprint)

当->>宏先插入并插入:foo时,这是不起作用的,这会给回显宏留下错误的参数。纠正这一问题的一种方法是引入额外的括号,但在我看来,这似乎很难看:

代码语言:javascript
复制
(->> :foo ((echo log/info "result")) clojure.pprint/pprint)

丑陋的意思是它闻起来像c宏。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-19 23:40:36

这里没有什么令人惊讶的事情,但是我认为echo扩展到一个函数会让人更难理解。macroexpand可以帮助说明所发生的事情:

代码语言:javascript
复制
(macroexpand '(->> :foo (echo prn "result") clojure.pprint/pprint))
=> (clojure.pprint/pprint (echo prn "result" :foo))

在这里,您可以看到->>正确地将参数线程处理到echo表单的第二个/最后一个位置,这不是您想要的,因为echo扩展到一个必须用:foo作为其唯一参数调用的函数。如果我们扩展您的另一个示例:

代码语言:javascript
复制
(macroexpand '(->> :foo
                   ((echo prn "result"))
                   clojure.pprint/pprint))
=> (clojure.pprint/pprint ((echo prn "result") :foo))

您可以看到,在线程处理之后,您的echo调用就像上面的工作示例一样形成为((echo prn "result") :foo)。这里的宏之间没有奇怪的交互,只是语法混乱,因为echo扩展到了必须调用的函数。

我认为如果echo扩展为代码而不是匿名函数,这将更加清晰/清晰(从宏扩展的角度来看)。但是,我认为没有宏就可以达到同样的效果,这通常是比较好的:

代码语言:javascript
复制
(defn echo [f x & args]
  (do (apply f x args)
      (last args))

(->> :foo
     (echo prn "result")
     (clojure.pprint/pprint))
;; "result" :foo
;; :foo
;; => nil

尽管还有其他方法来“监视”线程宏中的值。例如,试试这个:

代码语言:javascript
复制
(-> :foo
    (doto (prn "result"))
    (clojure.pprint/pprint))
;; :foo "result"
;; :foo
;; => nil
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49373381

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档