Clojure宏和引号

Clojure宏和引号,clojure,Clojure,我正在尝试“获取”clojure宏,并根据现有的are宏编写一个经过调整的are宏版本。 我想要的调整是使用签名[argv expr args]而不是[argv expr&args] 所以我试过了 (defmacro are2 [argv expr args] `(clojure.test/are ~arg ~expr ~@args)) 哪种类型的作品,除非它需要一个无引号的列表: (are2 [input] (= 0 input) (1 2 3)) (are2 [input] (= 0 i

我正在尝试“获取”clojure宏,并根据现有的
are
宏编写一个经过调整的
are
宏版本。 我想要的调整是使用签名
[argv expr args]
而不是
[argv expr&args]
所以我试过了

(defmacro are2 [argv expr args] `(clojure.test/are ~arg ~expr ~@args))
哪种类型的作品,除非它需要一个无引号的列表:

(are2 [input] (= 0 input) (1 2 3))
(are2 [input] (= 0 input) '(1 2 3))
我更希望看到一个引用的列表:

(are2 [input] (= 0 input) (1 2 3))
(are2 [input] (= 0 input) '(1 2 3))
但结果是:

Unable to resolve symbol: quote in this context.
如果我尝试

(are2 [input] (= 0 input) (list 1 2 3))
然后将
list
本身作为测试用例处理

我不明白的是什么/我如何通过宏中的引号(

)(1 2 3)
正在扩展为
(1 2 3))
,它有一个额外的
引号
符号和一个过多的列表级别,您可以通过macroexpand-1看到:

user> (macroexpand-1 '(are2 [input] (= 0 input) '(1 2 3)))
(clojure.test/are [input] (= 0 input) quote (1 2 3)) 
您可以通过先将引号包装为int,然后将其包装为rest,将其从列表中删除

 user> (defmacro are2 [argv expr args] 
          `(clojure.test/are ~argv ~expr ~@(first (rest args))))
#'user/are2
user> (macroexpand-1 '(are2 [input] (= 0 input) '(1 2 3)))
(clojure.test/are [input] (= 0 input) 1 2 3) 
然后作为测试运行:

user> (are2 [input] (= 0 input) '(1 2 3)

FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:1)
expected: (= 0 1)
  actual: (not (= 0 1))

FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:1)
expected: (= 0 2)
  actual: (not (= 0 2))

FAIL in clojure.lang.PersistentList$EmptyList@1 (NO_SOURCE_FILE:1)
expected: (= 0 3)
  actual: (not (= 0 3))
false 

宏扩展后可以显示表单的示例吗?您希望从
(are2[input](=0 input)(1 2 3))
最终得到什么?我希望它“执行clojure.test/are所做的任何操作,但不执行sig;-)中的&以下是clojure.test/are的代码:(defmocare[argv expr&args](if(or)(and(and(and(empty?argv)(empty?args));;捕获错误数量的args(and(pos?(count argv))(pos?(count args))(zero?(mod(count args)(count argv kа)'))`(temp/do模板~argv(is~expr)~@args)(throw)(IllegalArgumentException.“arg的数量与are的argv不匹配。”)但我想理解的是,为什么我重复使用的尝试失败了?还有一个问题。为什么需要将引号列表传递给宏?我不需要-,我想理解为什么它不起作用。引号是传递文字列表的常用方式?而传递未加引号的列表,如(1 2 3)通常情况下,如果这是解决问题的一种常见方式,那么就不能使用Long吗?或者我的问题本身有点特殊吗?事实上,(第一(其余))不等同于(eval…)?就“惯用”而言,我认为你的宏是好的。如果你想使用引用列表的语法,这就是宏的用途,那么给你带来更多的功能。。(首先(rest…)与(eval)的不同之处在于它不会启动编译器,并且会删除一级嵌套。