clojure支持参数重载的宏

问题

通过clojure.core/definline可以以方法的形态定义一个宏,但是definline这个宏却只支持固定的参数,在某些情况下需要支持不同参数的宏,从java的角度来说就是方法重载了。

支持重载的definline

大部分代码都是在definline的基础上魔改的。

(defmacro definline+
   [name & decl]
     (let [body (map (fn [[args# expr#]]
                      (let [f# (apply (eval (list `fn (list args# expr#))) args#)]
                                                                 `(~args# ~f#))) decl)
             alt-body (map (fn [[args# expr#]]
                `(~args# ~expr#)) decl)]
                `(do
                   (defn ~name ~@body)
                   (alter-meta! (var ~name) assoc :inline (fn ~name ~@alt-body))
                                        (var ~name))))])))]))

使用

比如noop 方法,现在可以支持2、3个参数了。

(definline+ noop
 ([a b]
  (or ~a ~b))
 ([a b c]
  (or ~a ~b ~c)))