在clojure中,在空集合上调用reduce *
会返回1.这非常令人惊讶。
我在创建阶乘函数时做了这个发现,定义如下:
(defn factorial [n] (reduce * (take-while #(> % 0) (iterate dec n))))
(factorial 0)
正确返回1
,而我不必为零编写特殊情况。
怎么样?
答案 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版本。