Skip to content

Instantly share code, notes, and snippets.

@sunng87
Last active March 23, 2024 00:57
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sunng87/372a0a45a07357569eb6 to your computer and use it in GitHub Desktop.
Save sunng87/372a0a45a07357569eb6 to your computer and use it in GitHub Desktop.
defprotocol with var-args support
(defmacro defprotocol+ [name & funcs]
(let [vararg-sym (symbol "&")
normalized-func-specs (map #(let [[n a] %]
(if (.contains a vararg-sym)
[(symbol (str n "*"))
(vec (remove (fn [_a]
(= _a vararg-sym)) a))
[n a]]
[n a]))
funcs)
vararg-funcs (filter #(> (count %) 2) normalized-func-specs)]
`(do
(defprotocol ~name
~@(map #(list (first %) (second %)) normalized-func-specs))
~@(map #(let [[prot-func prot-args original-spec] %
[n a] original-spec]
(list 'defn n a
(apply list prot-func prot-args))) vararg-funcs))))
(defmacro defrecord+ [name & forms]
`(defrecord ~name
~@(map #(if (list? %)
(let [[n a & forms] %
vararg-sym (symbol "&")]
(if (.contains a vararg-sym)
(apply list
(symbol (str n "*"))
(vec (remove (fn [_a] (= _a vararg-sym)) a))
forms)
%))
%) forms)))
(defmacro deftype+ [name & forms]
`(deftype ~name
~@(map #(if (list? %)
(let [[n a & forms] %
vararg-sym (symbol "&")]
(if (.contains a vararg-sym)
(apply list
(symbol (str n "*"))
(vec (remove (fn [_a] (= _a vararg-sym)) a))
forms)
%))
%) forms)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment