仍然试着把头包裹在Clojure身边。我可以看到如何在Haskell,Python等中实现以下内容,但还不知道如何在Clojure中编写它。感谢有人能告诉我基本结构。下面的伪代码。
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
这会是一堆让我们最后的表达吗?感谢。
答案 0 :(得分:20)
有很多可能性 - 这里有一些可以开始:
;;; 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
答案 1 :(得分:6)
你可以使用cond:
(cond
(= a bad _value) exception_a
(= b bad _value) exception_b
(= c bad _value) exception_c
:else default)
else是可选的;)
PS:我不知道如何在Clojure中抛出异常,所以不要告诉我代码不起作用
答案 2 :(得分:4)
没有宏的版本,未经测试,但我认为这样可行:
(defn check [bad xs]
(for [[f e] (partition 2 xs) :let [x (f)]]
(if (= x bad)
(throw (e))
x)))
(let [[a b c] (check bad [get-a #(ExceptionA.)
get-b #(ExceptionB.)
get-c #(ExceptionC.)])]
(do-action-with a b c))
我将函数中的异常包装起来,除非你需要抛出它们,否则不会生成它们。 Michał的宏版本更清晰。
答案 3 :(得分:0)
您应该在geta
,getb
,getc
函数中抛出异常。
那你的代码就是:
(let [ a (geta)
b (getb)
C (getc)]
( do something a b c))