Clojure中的动态记录
当我尝试从REPL运行以下代码时(播放动态记录): 我收到错误Clojure中的动态记录,clojure,macros,record,Clojure,Macros,Record,当我尝试从REPL运行以下代码时(播放动态记录): 我收到错误CompilerException java.lang.ClassCastException:clojure.lang.PersistentList无法转换为clojure.lang.Symbol,正在编译:(NO_SOURCE_PATH:23) 考虑到以下情况,我会问自己在哪里生成此PersistentList: user=> (symbol "rec2") rec2 user=> (vec (map symbol ["
CompilerException java.lang.ClassCastException:clojure.lang.PersistentList无法转换为clojure.lang.Symbol,正在编译:(NO_SOURCE_PATH:23)
考虑到以下情况,我会问自己在哪里生成此PersistentList:
user=> (symbol "rec2")
rec2
user=> (vec (map symbol ["f1" "f2"]))
[f1 f2]
但我真正的问题是为什么以下代码有效:
user=> (defrecord rec2 [f1 f2])
user.rec2
我也试过:
user=> (clojure.core/defrecord (clojure.core/symbol "rec1") (vec (clojure.core/map clojure.core/symbol ["f1" "f2"])))
CompilerException java.lang.RuntimeException: Can't refer to qualified var that doesn't exist, compiling:(NO_SOURCE_PATH:40)
(限定变量?唯一的区别是我完全限定了存在的函数名,顺便说一句)
很明显,我在理解Clojure defrecord宏时遗漏了一些东西,但我认为宏只是AST修饰符,所以如果我给它一个符号或某个分解为符号的东西,这是同一件事,所以我希望有人解释为什么正常形式有效而其他形式无效
蒂亚 问题如下:
defrecord
是一个宏,所有参数都不求值。它们传递给宏,所以它得到包含两个元素的列表:符号和字符串,而不是您所期望的rec2
。您可以尝试以下操作:
(eval `(defrecord ~(symbol "rec2") ~(vec (map symbol ["f1" "f2"]))))
它创建列表(DEFREC2[f1 f2])
,然后对其求值。但是我认为动态地评估一些代码不是一个好主意。可能还有其他方法可以做到这一点。问题如下:
defrecord
是一个宏,所有参数都不会计算。它们传递给宏,所以它得到包含两个元素的列表:符号和字符串,而不是您所期望的rec2
。您可以尝试以下操作:
(eval `(defrecord ~(symbol "rec2") ~(vec (map symbol ["f1" "f2"]))))
它创建列表(DEFREC2[f1 f2])
,然后对其求值。但是我认为动态地评估一些代码不是一个好主意。也许还有其他方法可以做到这一点。是的,有趣的是,我试图这样做是为了定义运行时记录。事实上,我注意到我在回答自己的问题:我试图用宏绕过宏问题!很好我可以用一个映射来做类似的事情,我唯一关心的是性能,因为Clojure记录是在类中编译的,映射是散列映射……是的,有趣的是,我试图这样做是为了定义运行时记录。事实上,我注意到我在回答自己的问题:我试图用宏绕过宏问题!很好我可以使用映射来实现类似的功能,我唯一关心的是性能,因为Clojure记录是在类中编译的,映射是散列映射。。。