Clojure动态intern的var抛错时栈追踪无对应引用的原因查询
问题解答
Clojure异常栈追踪的内容由函数对象编译期生成的字节码信息决定,和你修改的var元数据没有关联,核心原因如下:
- 你通过
eval生成的函数对象,编译时会被JVM分配自动生成的类名,类似你看到的eval27298/fn--27299,这个类名、编译时关联的源文件、行号信息都会直接写入字节码,是函数对象本身的固有属性,后续修改var的元数据不会改动已经生成的字节码内容。 intern操作只是把已经生成的函数对象绑定到你指定的var上,相当于给匿名对象增加了一个命名引用,不会修改函数对象本身的任何属性。
你可以通过两种方案解决栈追踪无有效标识的问题:
- 显式给
m-code内的函数指定名称:如果m-code中定义函数的代码是(fn [x] ...),修改为(fn my-expected-name [x] ...),编译生成的类名会携带你指定的函数名,栈追踪会直接显示该名称。 - 无法修改
m-code的情况下,eval时绑定编译上下文动态变量:
(let [x (binding [*ns* my-ns *file* "my_ns.clj" *line* 1 *column* 1] (eval m-code))] (intern my-ns my-sym x))
该方式会把你指定的源文件、行号信息写入编译生成的字节码,栈追踪就会显示对应信息而非默认的自动生成标识。
内容的提问来源于stack exchange,提问作者Kevin Kostlan
相关产品推荐
相关产品推荐

