Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基本Clojure:如何做一系列的if-then?_Clojure - Fatal编程技术网

基本Clojure:如何做一系列的if-then?

基本Clojure:如何做一系列的if-then?,clojure,Clojure,我还想把我的头缠在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

我还想把我的头缠在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

这会是一堆let,然后是一个最终表达式吗?谢谢。

有很多种可能性——以下是一些开始:

;;; 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

一个没有宏的版本,未经测试,但我认为它可以工作:

(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ł的宏版本更干净。

您可以使用cond:

(cond
  (= a bad _value) exception_a
  (= b bad _value) exception_b
  (= c bad _value) exception_c
  :else default)
else是可选的;)


PS:我不知道如何在Clojure中抛出异常,所以不要告诉我代码不工作

你应该在你的
geta
getb
getc
函数中抛出异常。 那么您的代码就是:

(let [ a (geta)
       b (getb)
       C (getc)]
   ( do something a b c))

回答得很好+1.我的答案被删除了。@Isaac Hodes:谢谢!顺便说一下,如果我们不愿意为所有调用硬编码一个异常类型,我想知道是否可以编写一个函数而不是宏。。。对异常类使用
proxy
感觉很愚蠢,但c.c.condition/c.c.error-kit可能会有所帮助吗?我真的需要在不久的将来对它们进行适当的调查。我还没有看过它们中的任何一个——它们看起来很有趣,而且很有能力……可能需要探索这些。谢谢你的指点!“~”不应该放在“e”和“val”之前吗?(新的)?@ubulonton:很好,谢谢!现在修复了。在这个更新中也是新的-额外的注释,一个变量版本的
不允许
和一元短路的例子。这三种情况下
坏值
都是一样的吗?
(做点a b c)
返回
c
。也许
(用b c做点什么)