你如何在Clojure早期从函数返回?

时间:2011-09-20 20:26:54

标签: clojure return

Common Lisp有return-from;当你想要从函数中提前返回时,Clojure中是否存在任何类型的return

8 个答案:

答案 0 :(得分:31)

当你需要提前摆脱计算时,你需要一种方法来做到这一点,而不是纯粹主义者的论证。通常,当您减少大型集合时需要它,并且某个值表示进一步处理集合没有意义。为此,实用的Clojure提供了reduced功能。

一个简单的例子就是,当一个数字序列相乘时,如果遇到零,你已经知道最终结果将为零,所以你不需要查看序列的其余部分。以下是使用reduced编码的方式:

(defn product [nums]
  (reduce #(if (zero? %2)
               (reduced 0.0)
               (* %1 %2))
          1.0
          nums))

reduced将您提供的值包装在sentinel数据结构中,以便reduce知道停止从集合中读取并立即返回reduced值。嘿,它的功能性很强,甚至可以!

如果您使用ifdo包裹在(println %1 %2)中,您可以看到正在发生的事情:

user=> (product [21.0 22.0 0.0 23.0 24.0 25.0 26.0])
1.0 21.0
21.0 22.0
462.0 0.0
0.0

user=> (product [21.0 22.0 23.0 24.0 25.0 26.0])
1.0 21.0
21.0 22.0
462.0 23.0
10626.0 24.0
255024.0 25.0
6375600.0 26.0
1.657656E8

答案 1 :(得分:25)

clojure中没有任何明确的return语句。如果你愿意的话,你可以使用catch / throw组合一起破解一些东西,但是因为clojure比普通的lisp功能更强大,你实际上需要在一些嵌套块的中间提前返回的可能性比CL小很多。我能看到返回语句的唯一“好”理由是当你以一种在clojure中不惯用的方式处理可变对象时。

我不会说它永远不会有用,但我认为在Clojure中,如果你的算法需要一个return语句,那就是一个主要的代码味道。

答案 2 :(得分:17)

除非您正在编写一些非常时髦的代码,否则您希望提前返回的唯一原因是,如果满足某些条件。但是由于函数总是返回最后一个表单的结果,if已经是这个函数 - 只需将你要返回的值放在if的正文中,如果是{{1}},它将返回该值条件得到满足。

答案 3 :(得分:14)

我不是Clojure的专家,但似乎没有那些构造试图更具功能性。看看Stuart Halloway所说的here

  

Common Lisp还支持从宏返回到“返回”   中间的一个功能。这鼓励了一种势在必行的风格   编程,Clojure不鼓励。

     

但是,您可以用不同的方式解决相同的问题。这是   返回示例,以功能样式重写,以便不   需要返回:

(defn pair-with-product-greater-than [n]
 (take 1 (for [i (range 10) j (range 10) :when (> (* i j) n)] [i j])))

即,使用延迟序列并根据条件返回值。

答案 4 :(得分:0)

已经提供的if选项可能是最佳选择,请注意,由于地图很简单,因此您可以始终在错误条件中返回{:error "blah"},并在有效条件中返回{result: x}

答案 5 :(得分:0)

Clojure中没有返回声明。即使您选择不使用ifwhen等流构造执行某些代码,该函数也会返回一些内容,在这些情况下nil。唯一的出路是抛出异常,但即使这样,它也会一直冒泡并杀死你的线程,或被函数捕获 - 这将返回一个值。

答案 6 :(得分:0)

您也可以使用cond。并且在某些情况下,如果您需要评估多个表达式,请使用do。 这是一个示例:

(defn fact [x]
  (cond
    (< x 0) (do (println (str x " is negative number"))
                (throw (IllegalArgumentException. "x should be 0 or higher")))
    (<= x 1) 1
    :else (* x (fact (- x 1)))))

答案 7 :(得分:-1)

简而言之,没有。如果这对你来说是一个真正的问题,那么你可以解决它 “the maybe monad”Monads具有高智力开销因此,对于许多情况,clojurians倾向于避免“如果失败的返回”风格的编程。

它有助于将功能分解为更小的功能,以减少摩擦。