macros - 在 clojure 宏中取消引用拼接并包装在向量中

标签 macros clojure

我最近开始学习 clojure,正在阅读 The Joy of Clojure 以掌握它。我有一个关于宏章节 (8) 中的代码段的问题,第 166 页

(defmacro domain [name & body]
  `{:tag :domain,                      ;`
    :attrs {:name (str '~name)},       ;'
    :content [~@body]})

据我了解,body是一个类似序列的结构,除了第一个参数之外的所有参数。如果是这样,在第三行中,我们为什么要取消引用拼接( ~@ )并再次将值放入向量中。为什么不做 ~body而不是 [~@body] ?有什么不同?

我很抱歉,但我发现很难掌握整个宏(来自 python)。

编辑:经过一些实验,我发现这有效,
(defmacro domain2 [name & body]
  `{:tag :domain,                      ;`
    :attrs {:name (str '~name)},       ;'
    :content '~body})

连同我从 Joost 的回答中得到的结果,我想我知道这里发生了什么。 body被表示为一个列表,所以如果我不放 '前面~body , clojure 将尝试对其进行评估。
user=> (domain "sh" 1 2 3)
{:content [1 2 3], :attrs {:name "sh"}, :tag :domain}

user=> (domain2 "sh" 1 2 3)
{:content (1 2 3), :attrs {:name "sh"}, :tag :domain}

最佳答案

我认为答案在于这个宏的意图。

快速查看提到的页面,似乎这个想法是使用 map 为域创建数据结构。选择的结构与 clojure.xml 库使用的结构相同。

确实,emit 函数会在您的代码和书中的代码中产生相似的结果,但是由于 clojure.xml 中的函数 parse 生成了一个带有矢量内容的 map ,因此最好在这里执行相同的操作,以便不要破坏依赖相同结构的其他代码。在这里也使用结构体以与 clojure.xml 保持一致可能是个好主意,例如现在 (content (domain ...))不起作用。

考虑到一般的数据结构,我发现在这里使用像向量这样的索引序列是个好主意,因为它可以说例如 ((:content domain-item) 1)访问第二项内容。更不用说子序列等。

关于macros - 在 clojure 宏中取消引用拼接并包装在向量中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5770127/

相关文章:

swift - 使用 swift4 在 xcode 中对单个项目使用不同的 GoogleService-Info.plist

java - "Help Arthur find his restricted class"或 "how can i make google app engine happy"

macros - Clojure 宏在调用时抛出 "CompilerException java.lang.IllegalStateException: Var clojure.core/unquote is unbound"

clojure - Lisp/Clojure 中的副作用

vba - AddDataField 从 "Report Filter"中删除字段

compilation - OpenMP 宏如何在幕后与预处理器/编译器和库本身协作?

c - header 看不到宏

clojure 对性能不佳的代码的性能

clojure - 在 Clojure (.clj) 脚本中导入 .jar (vaadin-6.4.8.jar) 文件

macros - objective-c - 如何编写宏