You can get quite a long way with just "if-let" "and" and "or" to express
the bailout logic.
Examples I find myself using all the time:
;; fallback / default values
(or (maybe-make-value) (make-fallback-value) (error "this shouldn't
happen!"))
;; bailout with nil return (assumes you are running operations for side
effects, and nil return means failure)
(and (operation1) (operation2) (operation3) :success)
;; let a value, with potential defaults
(if-let [value (or passed-value (try-to-find-default-value))] ....)
Apart from that, I found myself writing a few macros to allow early
bailouts from computations. My favourite currently is the "and-as->" macro,
which works like this:
(and-as-> (some-initial-value-expression) symbol
(do-something-with symbol)
(some-thing-else symbol)
(reduce some-fn symbol some-seq))
At each step, symbol is rebound to the result of the expression (like
"as->") unless the result is nil, in which case the whole expression bails
out and returns nil. So it is like a cross between "and" as "as->".
On Saturday, 23 March 2013 11:19:28 UTC+8, Russell Mull wrote:
>
> Hi Clojurians,
>
> I'm relatively new to the language and am trying to get used to its
> idioms. One thing I'm accustomed to doing in things like java and C# is
> checking values for validity and then bailing out early if they don't make
> sense. For example, without this idiom in java you might do:
>
> Object doSomething() {
>
> Integer a = someComputation();
> if(a != null) {
> Integer b = anotherComputation(a, 42);
> if(b != null && b.intValue() >= 0) {
> return a / b;
> }
> else {
> return null;
> }
> }
> else {
> return null;
> }
> }
> ... which is really only desirable if you believe in the "one exit point"
> school of imperative programming. It is of course much better to do this:
> Object doSomething() {
> Integer a = someComputation();
> if(a == null) { return null; }
>
> Integer b = anotherComputation(a, 42);
> if(b == null || b.intValue == 0) { return null; }
>
> return a / b;
> }
>
>
>
> ... which is much more literate. In Clojure, I have to write what is
> effectively the first form:
>
> (let [a (some-computation)]
> (if (nil? a)
> nil
> (let [b (another-computation a 42)]
> (if (or (nil? b) (= b 0))
> nil
> (/ a b)))))
>
> While more concise, it suffers the same readability problems as the first
> java version. I can easily imagine a macro to support this idiom:
>
> (let-check [a (some-computation)
> :check (nil? a) nil
> b (another-computation a 42)
> :check (or (nil? b) (< b 0)) nil]
> (/ a b))
>
>
> Which leads me to my question: does such a construct already exist? Or
> perhaps am I doing it wrong? I've googled around for this, but I'm not
> exactly sure what it's called.
>
> Cheers,
>
> Russell
>
>
--
--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
---
You received this message because you are subscribed to the Google Groups
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.