Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macros 在clojure宏中取消拼接和包裹向量_Macros_Clojure - Fatal编程技术网

Macros 在clojure宏中取消拼接和包裹向量

Macros 在clojure宏中取消拼接和包裹向量,macros,clojure,Macros,Clojure,我最近开始学习clojure,我正在阅读《clojure的快乐》来掌握它。我有一个关于宏第(8)章第166页代码段的问题 (defmacro domain [name & body] `{:tag :domain, ;` :attrs {:name (str '~name)}, ;' :content [~@body]}) 据我所知,body是一个类似于序列的结构,除了第一个参数外,它包含所有参数。如果是这样,在

我最近开始学习clojure,我正在阅读《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}

你说得很对~body已经是一个序列,所以除非需要保证:内容是一个向量(而不仅仅是可以排序的东西),否则[~@body]表达式可以被~body替换。

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

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

确实,emit函数将使用您的代码和本书中的代码生成类似的结果,但是当clojure.xml中的函数parse生成一个向量中包含内容的映射时,最好在这里执行相同的操作,以免破坏依赖相同结构的其他代码。在这里使用struct与clojure.xml保持一致可能是个好主意,例如现在的
(content(domain…)
不起作用


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

同样,可以在这里像这样发布本书中的一段代码,对吗?只是需要注意的一点,它是不加引号的拼接,而不是不加引号的拼接-slicing@Nicolas,更新了thanksThanks,但是,如果我将
[~@body]
替换为
~body
,并执行
(域“sh”1 2 3)
,我得到一个
java.lang.ClassCastException:java.lang.Integer不能转换为clojure.lang.IFn(无源文件:0)
。调用
macroexpand
也会引发相同的错误。您应该对引用的表达式调用macroexpand,否则它将在macroexpand到达它之前进行计算。Macroexpand是一个函数。谢谢Verneri,这很有意义:)