我想从矢量中得到最小的元素。为此,我使用了reduce
和min
函数。然而,提供我自己的实现的min
当我得到意想不到的结果:与标准min
返回0减少函数的意外结果
user=> (reduce (fn [x y] (< x y) x y) [1 2 3 2 1 0 1 2])
2
user=> (reduce min [1 2 3 2 1 0 1 2 3])
0
的降低预期。但是,当我提供自己的实现时,它返回2.我做错了什么?
我想从矢量中得到最小的元素。为此,我使用了reduce
和min
函数。然而,提供我自己的实现的min
当我得到意想不到的结果:与标准min
返回0减少函数的意外结果
user=> (reduce (fn [x y] (< x y) x y) [1 2 3 2 1 0 1 2])
2
user=> (reduce min [1 2 3 2 1 0 1 2 3])
0
的降低预期。但是,当我提供自己的实现时,它返回2.我做错了什么?
你缺少一个if
:
(reduce (fn [x y] (if (< x y) x y)) ...)
^-- note the if
工作正常。 :-)
与reduce一起使用的fn可能需要处理3个arities - 0,1和2个参数。
您在函数正文周围缺少if
。现在会发生什么是:
user> (use 'clojure.contrib.trace)
nil
user> (defn foo [x y] (< x y) x y)
#'user/foo
user> (dotrace [foo] (reduce foo [1 2 3 2 1 0 1 2]))
TRACE t2229: (foo 1 2)
TRACE t2229: => 2
TRACE t2230: (foo 2 3)
TRACE t2230: => 3
TRACE t2231: (foo 3 2)
TRACE t2231: => 2
TRACE t2232: (foo 2 1)
TRACE t2232: => 1
TRACE t2233: (foo 1 0)
TRACE t2233: => 0
TRACE t2234: (foo 0 1)
TRACE t2234: => 1
TRACE t2235: (foo 1 2)
TRACE t2235: => 2
2
换句话说,你总是在传递给函数返回y,所以在最后一次迭代2返回,因为2是你减少了序列的最后一个号码。
还要注意的是min
已经基于reduce
:
(defn min
"Returns the least of the nums."
([x] x)
([x y] (if (< x y) x y))
([x y & more]
(reduce min (min x y) more)))
不是真的。 'min'的实现提供了一个'reduce'的例子,它与一个在Clojure中没有无限实现的函数一起使用。此外,Clojure的“reduce”从未使用过一元案例。一个长度为1的序列总是被缩减为它唯一的元素。如果你打算处理空序列(如果你愿意把它们当作错误的输入,你可以不使用它),并且你肯定需要一个二进制的例子(如果你永远不会去处理长度> 1的序列,无论如何都没有必要使用'reduce')。 – 2010-05-12 11:48:31
@Michal,你说的完全正确。 0和2个参数。 – dnolen 2010-05-12 13:59:43