很抱歉,如果这个问题没有任何意义。
我目前正在编写一个小应用程序,我希望将一些函数“链接”起来,形成更广泛的计算。
例如,我有一个函数调用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
,但我仍然需要在开始时使用这些检查来丢弃我的代码
任何想法或回复都会非常感激
答案 0 :(得分:4)
Clojure Contrib的algo.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)