How do you return from a function early in Clojure?

后端 未结 8 1258
不知归路
不知归路 2020-12-08 13:48

Common Lisp has return-from; is there any sort of return in Clojure for when you want to return early from a function?

相关标签:
8条回答
  • 2020-12-08 14:13

    When you need to bail out of a computation early, you need a way to do that, not an argument from purists. Usually you need it when you're reducing a big collection and a certain value indicates that there's no point in further processing the collection. To that end, the ever-practical Clojure provides the reduced function.

    A simple example to illustrate is that when multiplying a sequence of numbers, if you encounter a zero, you already know that the final result will be zero, so you don't need to look at the rest of the sequence. Here's how you code that with reduced:

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

    reduced wraps the value you give it in a sentinel data structure so that reduce knows to stop reading from the collection and simply return the reduced value right now. Hey, it's pure-functional, even!

    You can see what's going on if you wrap the above if in a do with a (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
    
    0 讨论(0)
  • 2020-12-08 14:15

    As an alternative you could use cond . And if on some conditions you would need to evaluate multiple expressions use do. Here is an example:

    (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)))))
    
    
    0 讨论(0)
提交回复
热议问题