Extensible macros (A flatter cond follow-up)
I pushed Utils out. It features reduce-by
but also variations on cond
(the ones introduced in the comments of A Flatter Cond) and if-let
.
cond
supports the following operators: :let
, :when
, :when-let
and vectors in test position are treated as the binding form to a if-let
(thus setting the local bindings) for the “then” expression not for the rest of the cond
.
if-let
supports :let
to introduce new bindings without testing their expression for truth.
One notable twist to these macros is that thanks to net.cgrand.xmacros
they are extensible: new operators can safely be participated to the macros (proper namespacing is enforced). See the cond
implementation, abbreviated below:
(defmacro cond "An extensible variation on cond. Trailing else is supported. keywords in test position are treated as operators. Operators impls signature is [rhs else] where rhs is the \"then\" expression next to the operator." [& clauses] (when-let [[op rhs & more-clauses] (seq clauses)] (if (next clauses) (x/expand-op op rhs `(cond ~@more-clauses)) test))) (x/defdefault-op cond [test-expr then else] (if (vector? test-expr) `(if-let ~test-expr ~then ~else) `(if ~test-expr ~then ~else))) (x/defop cond :let "Introduces local bindings." [bindings cont] `(let ~bindings ~cont)) (x/defop cond :when "Short-circuits the rest of the cond if false" [test-expr cont] `(when ~test-expr ~cont)) (x/defop cond :when-let "Short-circuits the rest of the cond if false and introduces local bindings." [bindings cont] `(when-let ~bindings ~cont))