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 clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
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 clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to