Created
May 26, 2016 22:45
-
-
Save Engelberg/9fc1264f938077cf03eee112ebed1768 to your computer and use it in GitHub Desktop.
Better cond
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns utils.cond | |
"A collection of variations on Clojure's core macros. Let's see which features | |
end up being useful." | |
{:author "Christophe Grand"} | |
(:refer-clojure :exclude [cond when-let if-let])) | |
(defmacro if-let | |
"A variation on if-let where all the exprs in the bindings vector must be true. | |
Also supports :let." | |
([bindings then] | |
`(if-let ~bindings ~then nil)) | |
([bindings then else] | |
(if (seq bindings) | |
(if (= :let (bindings 0)) | |
`(let ~(bindings 1) | |
(if-let ~(subvec bindings 2) ~then ~else)) | |
`(let [test# ~(bindings 1)] | |
(if test# | |
(let [~(bindings 0) test#] | |
(if-let ~(subvec bindings 2) ~then ~else)) | |
~else))) | |
then))) | |
(defmacro when-let | |
"A variation on when-let where all the exprs in the bindings vector must be true. | |
Also supports :let." | |
[bindings & body] | |
`(if-let ~bindings (do ~@body))) | |
(defmacro cond | |
"A variation on cond which sports let bindings and implicit else: | |
(cond | |
(odd? a) 1 | |
:let [a (quot a 2)] | |
(odd? a) 2 | |
3). | |
Also supports :when-let and binding vectors as test expressions." | |
[& clauses] | |
(when-let [[test expr & more-clauses] (seq clauses)] | |
(if (next clauses) | |
(if (= :let test) | |
`(let ~expr (cond ~@more-clauses)) | |
(if (= :when test) | |
`(when ~expr (cond ~@more-clauses)) | |
(if (= :when-let test) | |
`(when-let ~expr (cond ~@more-clauses)) | |
(if (vector? test) | |
`(if-let ~test ~expr (cond ~@more-clauses)) | |
`(if ~test ~expr (cond ~@more-clauses)))))) | |
test))) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment