程序流程 - 如果一个计算失败,则退出操作

时间:2011-11-14 12:49:12

标签: clojure

很抱歉,如果这个问题没有任何意义。

我目前正在编写一个小应用程序,我希望将一些函数“链接”起来,形成更广泛的计算。

例如,我有一个函数调用web服务并返回hash-map作为结果,或者nil如果是错误或出错了。链中的下一个函数接受映射并进行一些进一步处理,然后将其传递给下一个函数......依此类推。

问题是,如果第一个函数失败,它会将nil传递给下一个函数,这将抛出一个nullpointer(或其他),我不希望它甚至达到这个阶段。 换句话说,如果链中的一个项失败,我希望整个计算失败。

e.g。

;successful computation = function1 returns W -> function2 returns X -> function3 returns Y -> function4 returns Z -> Z
;failed computation = function1 returns W -> function2 returns X -> function3 returns nil -> nil
(-> (function1 "http://webservice.com") (function2) (function3) (function4))

事情是我不想在开始的时候用if(nil? arg)乱扔我的每个函数,理想情况下我想要一个可以照顾我的抽象但我不是真的关于Clojure中可用的内容

我正在考虑采用Scala样式Option类型,可以是Some(value)None,但我仍然需要在开始时使用这些检查来丢弃我的代码

任何想法或回复都会非常感激

3 个答案:

答案 0 :(得分:4)

Clojure Contribalgo.monad包含Scala调用{mon}的monad的实现。Option。它被称为maybe-m,其工作原理是将nil视为None。您可以像这样使用它:

(ns mulk.monads-test
  (:refer-clojure)
  (:use clojure.repl
        clojure.algo.monads))

(defn function1 [x]
  x)

(defn function2 [x]
  (+ x 10))

(defn function3 [x]
  (* x 2))

(defn calc-stuff [thing]
  (domonad maybe-m
    [x1 (function1 thing)
     x2 (function2 x1)
     x3 (function3 (+ x2 10))]
    x3))

 (calc-stuff 10)   ;=> 60
 (calc-stuff nil)  ;=> nil

答案 1 :(得分:4)

clojure.contrib.core具有-?>宏,可以完全按照您的意愿执行。

请参阅http://clojuredocs.org/clojure_contrib/clojure.contrib.core/-_q%3E

答案 2 :(得分:1)

您可以定义一个辅助函数来链接函数调用并检查之间的nil值:

(defn chain [v & functions]
  (cond (nil? v) nil
        (empty? functions) v
        :else (recur ((first functions) v) (rest functions))))

然后这样称呼:

(chain "http://webservice.com" function1 function2 function3 function4)