减少功能的意外结果

时间:2010-05-11 22:40:53

标签: clojure

我想从矢量中获取最小元素。为此,我使用了reducemin函数。但是,在提供我自己的min实现时,我会得到意想不到的结果:

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

标准min的reduce按预期返回0。但是,当我提供自己的实现时,它返回2.我做错了什么?

3 个答案:

答案 0 :(得分:8)

您错过了if

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

工作正常。 : - )

答案 1 :(得分: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)))

答案 2 :(得分:-1)

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