Skip to content

Instantly share code, notes, and snippets.

@mcav
Created April 6, 2013 00:54
Show Gist options
  • Save mcav/5323781 to your computer and use it in GitHub Desktop.
Save mcav/5323781 to your computer and use it in GitHub Desktop.
Type-checking an API method in 20 lines of Clojure.
(defmacro defapi [method metadata args & forms]
`(defn ~method [& {:as named-params#}]
;; preprocess arguments
(doseq [arg# '~args]
(let [param# (get named-params# (keyword arg#))
optional# (:optional (meta arg#))]
;; ensure all required arguments were provided
(when (and (not optional#) (nil? param#))
(throw (IllegalArgumentException.
(format "Argument \"%s\" is required and was not provided." (name arg#)))))
;; type-check arguments if they have been type-hinted
(let [type# (resolve (:tag (meta arg#)))]
(when (and (not (and optional# (nil? param#)))
(and type# (not (instance? type# param#))))
(throw (IllegalArgumentException. (format "Expected \"%s\" to be of type %s (was %s)."
(name arg#) type# (type param#))))))))
;; set up the bindings
(let [{:keys ~args} named-params#]
~@forms)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment