Reputation: 1311
I've got the following code:
(cond
(case-1? (compute-1 x)) (compute-1 x)
(case-2? (compute-2 x)) (compute-2 x)
(case-3? (compute-3 x)) (compute-3 x))
I want to avoid repeated computations of compute-1
, compute-2
, and compute-3
. One option is:
(let [result-1 (compute-1 x)
result-2 (compute-2 x)
result-3 (compute-3 x)]
(cond
(case-1? result-1) result-1
(case-2? result-2) result-2
(case-3? result-3) result-3))
Now I'm not repeating computations, but instead if now (case-1? result-1)
evaluates to true, result-2
and result-3
were computed for no reason.
Behaviorally I want something like this:
(let [result-1 (compute-1 x)]
(if (case-1? result-1)
result-1
(let [result-2 (compute-2 x)]
(if (case-2? result-2)
result-2
(let [result-3 (compute-3 x)]
(if (case-3? result-3)
result-3))))))
However this code is obviously quickly becoming unmanageable. Is there a better solution to this problem?
Upvotes: 2
Views: 75
Reputation: 1552
There's a library called better cond that solves exactly that problem with a macro.
It's used like this:
(ns foo.core
(:require
[better-cond.core :as b]))
(b/cond
:let [result-1 (compute-1 x)]
(case-1? result-1) result-1
:let [result-2 (compute-2 x)]
(case-2? result-2) result-2
:let [result-3 (compute-3 x)]
(case-3? result-3) result-3)
That snippet will macroexpand to code that's similar to your last example.
Upvotes: 3