Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating Clojure code with macro containing type hints

I'm trying to generate some Clojure code with type hints, however the type hints seem to disappear whenever I build some code (they also don't function when the code is compiled)

e.g.

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

=> (clojure.core/let [user/b (user/create-buffered-image)] (.getRGB user/b 0 0))

I'm not precisely sure why the type hint is disappearing, but I assume it is something to do with how metatdata is handled by the reader.

What's the right way to create correct type hints in generated code?

like image 367
mikera Avatar asked Aug 12 '12 03:08

mikera


1 Answers

There are two answers to this question. To answer your specific question: in the actual code you just posted, nothing is wrong: it's working just fine. (set! *print-meta* true) and try again, and you'll see the metadata annotation. It just doesn't normally print.

But, in general this is not the right way to do things from a macro, and you will have trouble before long. Remember, you don't want metadata on the forms the macro evaluates, you want metadata on the forms the macro emits. So, a more accurate solution is to use with-meta on the symbols or forms that you want to attach metadata to - or, if they're user-supplied forms, you should usually use vary-meta so that you don't discard the metadata they added explicitly. For example,

(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))
like image 158
amalloy Avatar answered Oct 24 '22 11:10

amalloy