2010-05-11 119 views
6

我想从矢量中得到最小的元素。为此,我使用了reducemin函数。然而,提供我自己的实现的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.我做错了什么?

回答

8

你缺少一个if

(reduce (fn [x y] (if (< x y) x y)) ...) 
        ^-- note the if 

工作正常。 :-)

-1

与reduce一起使用的fn可能需要处理3个arities - 0,1和2个参数。

+1

不是真的。 'min'的实现提供了一个'reduce'的例子,它与一个在Clojure中没有无限实现的函数一起使用。此外,Clojure的“reduce”从未使用过一元案例。一个长度为1的序列总是被缩减为它唯一的元素。如果你打算处理空序列(如果你愿意把它们当作错误的输入,你可以不使用它),并且你肯定需要一个二进制的例子(如果你永远不会去处理长度> 1的序列,无论如何都没有必要使用'reduce')。 – 2010-05-12 11:48:31

+0

@Michal,你说的完全正确。 0和2个参数。 – dnolen 2010-05-12 13:59:43

5

您在函数正文周围缺少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)))