Skip to content →

Dynamic type hints in Clojure macros

Sometimes, one wants to write a Clojure macro to assist in Java interoperability, where the object types are determined by the arguments to the macro. In this situation, the normal strategy of using a #^class type hint doesn’t work, since the class isn’t known at read time. Here’s a very contrived example, where the macro declare-first-char defines a function first-char, which calls the (.charAt % 0) method on its argument. The class for the type hint is passed as an argument to the macro.

user> (set! *warn-on-reflection* true)
true
 
user> (defmacro declare-first-char [cls]
	(let [x (gensym)]
	  `(defn first-char [~(with-meta x {:tag cls})] 
             (.charAt ~x 0))))
#'user/declare-first-char
 
user> (declare-first-char String)
#'user/first-char ; No reflection warning!
 
user> (first-char "test")
\t

The key here is the [~(with-meta x {:tag cls})] fragment, which replaces the normal [#^String x#] version that could be used if the type was known in advance.

Published in Clojure

One Comment

  1. Konrad Grzanek

    Great advice. That’s exactly what I was searching for. Thanks !!!

Leave a Reply

Your email address will not be published. Required fields are marked *