Clojure宏生成的代码中的反射警告

Clojure宏生成的代码中的反射警告,clojure,macros,Clojure,Macros,我不明白为什么下面的代码会产生反射警告: (设置!*反射时警告*true) (defmacro my macro[k]`(.length~(with meta k{:tag String}))) (定义my-fun1[k](我的宏k)) ;; 反射警告,/tmp/form-init2370243866132870536。clj:1:18-无法解析对字段长度的引用。 使用macroexpand-1显示生成的代码确实具有typehint,如果我在不使用宏的情况下手动编写相同的代码,则不会出现反射警

我不明白为什么下面的代码会产生反射警告:

(设置!*反射时警告*true)
(defmacro my macro[k]`(.length~(with meta k{:tag String})))
(定义my-fun1[k](我的宏k))
;; 反射警告,/tmp/form-init2370243866132870536。clj:1:18-无法解析对字段长度的引用。
使用
macroexpand-1
显示生成的代码确实具有typehint,如果我在不使用宏的情况下手动编写相同的代码,则不会出现反射警告:

(设置!*打印元*true)
(宏扩展-1'(我的宏k))
;; (.length^java.lang.String k)
(定义my-fun2[k](.length^字符串k))
;; 一切正常,无反射警告
对该函数进行基准测试表明,警告不仅仅是一种转移视线的行为,反射实际上发生在运行时:

(时间(减少+(映射my-fun1(重复1000000“测试”))
;; “运行时间:3080.252792毫秒”
(时间(减少+(映射my-fun2(重复1000000“测试”))
;; “运行时间:275.204877毫秒”

标记应该是符号,而不是类。因此,以下代码起作用:

(defmacro my-macro [k] `(.length ~(with-meta k {:tag `String})))
事实上,这是在:

:标记

命名类或类对象的符号,表示Java 变量中对象的类型,或者如果对象是 fn


事实上,
macroexpand-1
显示了一个无效的类型提示,但看起来与正确的类型提示完全相同,这是非常误导的:)

当我运行
macroexpand-1
行时,我没有看到类型提示。然而,我认为宏观经济有问题;它不接受文本字符串:
(我的宏“foo”);=>java.lang.ClassCastException:java.lang.String不能强制转换为clojure.lang.IObj
。您应该看到类型提示。您确定要将
*print meta*
设置为true吗?请注意,在
字符串
上使用反引号稍微正确一些,而不是普通的引号。对于java.lang中的类也是如此,因为这些类在所有名称空间中都会导入,因此非限定引用是有效的,但是如果尝试使用类似ArrayList的类,它将只在导入了java.util.ArrayList的名称空间中有效。