We have some->
and some->>
which are great for pipelines where nil
is a terminating value but there are a lot of times where you might want a pipeline to halt with more information.
At work, for example, we have an image processing pipeline where each step either produces enhanced image information or an error hash map explaining why the pipeline cannot proceed. We currently have to explicitly code the error check into every step of the pipeline.
Adding pred->
and pred->>
macros which accept [pred expr & forms]
but were similar in structure to some->
and some->>
would make this a lot cleaner.
some->
and some->>
could essentially then be pred-> some?
and pred->> some?
(defmacro pred->
"When expr satisfies pred, threads it into the first form (via ->),
and when that result satisfies pred, through the next etc"
[pred expr & forms]
(let [g (gensym)
p pred
steps (map (fn [step] `(if (~p ~g) (-> ~g ~step) ~g))
forms)]
`(let [~g ~expr
~@(interleave (repeat g) (butlast steps))]
~(if (empty? steps)
g
(last steps)))))