使用包含类型提示的宏生成Clojure代码

mik*_*era 20 macros code-generation metaprogramming clojure type-hinting

我正在尝试使用类型提示生成一些Clojure代码,但是每当我构建一些代码时类型提示似乎都消失了(它们在代码编译时也不起作用)

例如

`(let [^BufferedImage b (create-buffered-image)] 
   (.getRGB b 0 0))

=> (clojure.core/let [user/b (user/create-buffered-image)] (.getRGB user/b 0 0))
Run Code Online (Sandbox Code Playgroud)

我不确定为什么类型提示正在消失,但我认为它与读者处理metatdata的方式有关.

在生成的代码中创建正确类型提示的正确方法是什么?

ama*_*loy 32

这个问题有两个答案.要回答你的具体问题:在刚发布的实际代码中,没有错:它工作得很好.(set! *print-meta* true)然后再试一次,你会看到元数据注释.它通常不会打印.

但是,一般来说,这不是从宏观做事的正确方法,不久之后你就会遇到麻烦.请记住,您不希望宏评估的表单元数据,您希望宏发出的表单元数据.因此,更准确的解决方案是with-meta在要附加元数据的符号或表单上使用- 或者,如果它们是用户提供的表单,则通常应该使用,vary-meta以便不丢弃它们明确添加的元数据.例如,

(defmacro with-image [name & body]
  (let [tagged-name (vary-meta name assoc :tag `BufferedImage)
    `(let [~tagged-name (create-buffered-image)
       ~@body)))

(with-image i (.getRGB i 0 0))
Run Code Online (Sandbox Code Playgroud)