Ves*_*sna 0 macros record clojure
我写了一个用于创建记录的宏
(defmacro def-entity [name & value]
`(do
(defrecord ~name (vector ~@value))
))
Run Code Online (Sandbox Code Playgroud)
我创建了一个实体
(def-entity p a b)
Run Code Online (Sandbox Code Playgroud)
但是当我尝试创建一个具体的实例(def something(p."a""b"))时,我收到此消息java.lang.IllegalArgumentException:找不到类user.p(repl-1:40)的匹配ctor.所以我必须提供3个参数,像这样(def某人(p."a""b""x"))并且它放置像这样的值
(-> someone :a)
"b"
(-> neko :p)
nil
Run Code Online (Sandbox Code Playgroud)
我似乎不明白发生了什么?
由于defrecord它本身就是一个宏,并希望记录的字段作为矢量文字传递,你应该更好地避免传递一个引用向量的符号,并真正构建一个矢量文字作为宏工作的一部分:
(defmacro defentity [name & values]
`(defrecord ~name ~(vec values)))
Run Code Online (Sandbox Code Playgroud)
结果如下:
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"}
Run Code Online (Sandbox Code Playgroud)
相反,您的版本会产生以下结果,它不使用矢量文字作为输入defrecord:
user=> (macroexpand-1 '(def-entity p a b))
(do (clojure.core/defrecord p (clojure.core/vector a b)))
Run Code Online (Sandbox Code Playgroud)
事实上,我甚至无法在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)
Run Code Online (Sandbox Code Playgroud)