Macros 用于创建记录的Clojure宏

Macros 用于创建记录的Clojure宏,macros,clojure,record,Macros,Clojure,Record,我写了一个宏来创建记录 (defmacro def-entity [name & value] `(do (defrecord ~name (vector ~@value)) )) 我创建了一个实体 (def-entity p a b) 但是当我尝试创建一个具体的实例时 定义某物p。a b 我得到一条消息java.lang.IllegalArgumentException:找不到类user.p repl-1:40的匹配构造函数。 所以我必须提供3个参数,像这样 有

我写了一个宏来创建记录

(defmacro def-entity [name & value]
 `(do
    (defrecord ~name (vector  ~@value))
    ))
我创建了一个实体

(def-entity p a b)
但是当我尝试创建一个具体的实例时 定义某物p。a b 我得到一条消息java.lang.IllegalArgumentException:找不到类user.p repl-1:40的匹配构造函数。 所以我必须提供3个参数,像这样 有人吗。a b x 它把这些值放在下面

 (-> someone :a)
 "b"
 (-> neko :p)
 nil
我似乎不明白发生了什么事?

使用[~@value]而不是vector~@value:

实际上,你的变体对我根本不起作用。def实体p a b引发异常。但我可以建议def实体pab展开为defcrecord p vector ab,defcrecord本身是一个宏,它将第二个参数作为字段列表。第二个参数是向量AB——它是一个包含3个元素的列表。所以它创建了一个包含3个字段的记录:vector、a和b。检查有人返回的向量。

由于defrecord本身是一个宏,并且希望记录的字段作为向量文本传入,因此最好避免传递引用向量的符号,并真正构造一个向量文本作为宏工作的一部分:

(defmacro defentity [name & values]
  `(defrecord ~name ~(vec values)))
其结果是:

user=> (macroexpand-1 '(defentity p a b))
(clojure.core/defrecord p [a b])
user=> (defentity Test foo bar)
user.Test
user=> (def s (Test. "foo" "bar"))
#'user/s
user=> s
#user.Test{:foo "foo", :bar "bar"}
相比之下,您的版本会产生以下结果,即不使用向量文字作为defrecord的输入:

事实上,我甚至不能在Clojure 1.4中使用您的版本:

user=> (def-entity w x y)
CompilerException java.lang.RuntimeException: Can't use qualified name as parameter: clojure.core/vector, compiling:(NO_SOURCE_PATH:1) 

谢谢。。。我知道这是一些基本的东西。。。我使用Clojure 1.2版…事实上,这些天我正计划升级到1.4版…很高兴它有所帮助!请考虑接受答案:-请在DeMe宏的结尾添加一个闭合括号;
user=> (macroexpand-1 '(def-entity p a b))
(do (clojure.core/defrecord p (clojure.core/vector a b)))
user=> (def-entity w x y)
CompilerException java.lang.RuntimeException: Can't use qualified name as parameter: clojure.core/vector, compiling:(NO_SOURCE_PATH:1)