Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Basic Clojure: How to do a series of if-then?

Tags:

clojure

Still trying to wrap my head around Clojure. I can see how to implement the following in Haskell, Python, etc. but do not yet understand how to write this in Clojure. Appreciate if someone can show me the basic structure. Pseudo-code below.

a = get_a
if (a == bad_value) then throw exception_a
b = get_b
if (b == bad_value) then throw exception_b
c = get_c
if (c == bad_value) then throw exception_c
...
do_action_with a b c

Would this be a bunch of lets and then a final expression? Thanks.

like image 257
qrest Avatar asked Aug 24 '10 03:08

qrest


1 Answers

There is a number of possibilities -- here's a few for a start:

;;; 1. direct translation
; _ is the idiomatic "I don't care" identifier in Clojure
(let [a (get-a)
      _ (if (= a bad-value) (throw (Exception. "Foo!")))
      b (get-b)
      _ (if (= b bad-value) (throw (Exception. "Foo!")))
      ...]
  (do-action-with a b ...))

;;; 2. abstract the pattern away
(defmacro disallow
  ([expr val] ; binary version with default exception type;
              ; omit if explicit type is to be required
     (disallow (list* &form [Exception]) &env expr val Exception))
  ([expr val e]
     `(let [actual# ~expr]
        (if (= actual# ~val)
          (throw (new ~e (str "Value " ~val " not allowed.")))
          actual#))))

(let [a (disallow (get-a) ExceptionA)
      b (disallow (get-b) ExceptionB)
      ...]
  ...)

;;; 3. monadic short-circuiting
(use '[clojure.contrib.monads :only [domonad maybe-m]])
; ...now do it more or less as in Haskell;
; you can use :when in domonad for monads with m-zero
; -- the syntax is that of for / doseq:
(doseq [sym '[a b c]] (intern *ns* sym (atom 0)))
(domonad maybe-m
  [a @a
   :when (pos? a)
   b @b
   :when (neg? b)
   c @c
   :when (not (zero? c))]
  (* a b c))
; => 0
(dorun (map reset! [a b c] [3 -2 1]))
(domonad maybe-m
  ; same as above
  )
; => -6
like image 121
Michał Marczyk Avatar answered Sep 17 '22 16:09

Michał Marczyk