在Clojure宏中使用绑定时出现空指针异常
我在执行一个宏进行Java互操作时遇到了一个空指针异常,我不知道为什么 我使用带有嵌套数据的映射设置Java对象的字段,由于映射键的名称与对象的字段名称相同,我创建了一个宏:在Clojure宏中使用绑定时出现空指针异常,clojure,Clojure,我在执行一个宏进行Java互操作时遇到了一个空指针异常,我不知道为什么 我使用带有嵌套数据的映射设置Java对象的字段,由于映射键的名称与对象的字段名称相同,我创建了一个宏: (defmacro设置关键点![pose m k klst] `(集合!(.~pose~(symbol(name k))) (双数组(map#)((~(keyword(name k))~m))~klst))) 为了进行测试,我将pse定义为一个初始化的Java对象,将感兴趣的字段设置为零,并将mp定义为一个仍能工作的简化
(defmacro设置关键点![pose m k klst]
`(集合!(.~pose~(symbol(name k)))
(双数组(map#)((~(keyword(name k))~m))~klst)))
为了进行测试,我将pse
定义为一个初始化的Java对象,将感兴趣的字段设置为零,并将mp
定义为一个仍能工作的简化映射:
(defmp{:pos{:x1:y2})
现在出现了奇怪的行为。使用显式键入的参数执行设置键!
:
user>(设置键!pse mp:pos[:x:y])
#
但是,如果我在a中使用运行代码,让
调用:
user>(让[x:posy[:x:y]]
(设置键!pse mp x y))
我得到一个空指针异常,消息为“No message”。这里有什么问题
编辑:我用(def pse(pose_.)定义了pse
,pose_t
是一个生成的类,pose_t()
构造函数初始化其字段中的所有数组,但不初始化值。简化示例中类代码的相关行为:
public-double-pos[];
公众姿势(){
pos=新双精度[3];
}
宏参数不求值,因此~(关键字(名称k))
扩展为-大致-(关键字(名称(引号x))
-即:x,而不是:pos
至少我想这是问题所在。如果不是,如果你能为pse
添加一个定义就好了
附录:您可以通过评估以下内容来检查宏实际扩展到什么:
user> (macroexpand-1 '(set-keys! pse mp x y))
(set! (. pse x) (clojure.core/double-array (clojure.core/map
(fn* [p1__2066__2067__auto__] (p1__2066__2067__auto__ (:x mp))) y)))
注:x
附录2:(.obj字段)
实际上也不计算字段
,这意味着您必须使用java反射来使字段参数动态。您是对的,这就是问题所在。对于这一部分,我可以将~(关键字(名称k))
更改为简单的~k
,但是~(符号(名称k))
扩展到x
而不是pos
。为什么unquote不强制x
求值?是因为宏扩展发生在运行之前?如果是这样,我如何以编程方式将参数发送到宏?我最终必须使用设置键对集合调用map
对传递给map的函数进行de。是的,这是因为宏操作代码而不是值。unquote不求值,它插入文字表达式(代码段)这是作为参数给出的。据我所知,您可以使用普通函数和java反射或关键字到字段赋值函数的固定映射更清楚地编写所需的功能。也就是说,如果您确实需要动态传递值-如果您可以“静态”传递字段名,您已经有了一个有效的解决方案。