为什么(reduce * [])评估为1?

时间:2014-05-29 15:26:56

标签: clojure

在clojure中,在空集合上调用reduce *会返回1.这非常令人惊讶。

我在创建阶乘函数时做了这个发现,定义如下:

(defn factorial [n] (reduce * (take-while #(> % 0) (iterate dec n))))

(factorial 0)正确返回1,而我不必为零编写特殊情况。 怎么样?

2 个答案:

答案 0 :(得分:7)

检查*+的代码表明这两个函数通过返回操作的标识来实现0-arity情况。在*的情况下,代码是(删除了dosctring和元数据):

(defn *
  ([] 1)
  ([x] (cast Number x))
  ([x y] (. clojure.lang.Numbers (multiply x y)))
  ([x y & more]
     (reduce1 * (* x y) more)))

答案 1 :(得分:0)

这里的要点是reduce的行为。在

(reduce f s)

...如果s为空,则调用返回(f)

由于(*)1

(reduce * ())
; 1

reduce并不关心1*的身份。虽然1也是/的正确身份,

(reduce / ())
; ArityException Wrong number of args (0) passed to: core$-SLASH- ...

...因为,正如/所述,0并未声明{{1}} arity版本。