Clojure中两个reduce表达式执行结果不一致的原因咨询
Clojure中两个reduce表达式执行结果不一致的原因咨询
嘿,我来帮你拆解这两个reduce为啥结果差这么多~核心问题出在初始累加器的处理逻辑上,咱们一步步看:
首先,你给两个reduce的初始累加器都是{},也就是第一次调用匿名函数的时候,:minimum和:maximum的值都是nil,这是关键的起点。
先看第一个reduce的问题
(reduce (fn [{:keys [minimum maximum]} new-number] {:minimum (if (and minimum (< new-number minimum)) new-number minimum) :maximum (if (and maximum (> new-number maximum)) new-number maximum)}) {} [5 23 5004 845 22])
- 处理
:minimum时,判断条件是(and minimum (< new-number minimum)):第一次执行时,minimum是nil,and表达式直接返回nil,条件不成立,所以返回的还是minimum也就是nil。后面每一次循环,minimum始终是nil,这个条件永远满足不了,最后:minimum就一直是nil。 - 同理,
:maximum的判断条件(and maximum (> new-number maximum)),因为maximum一开始是nil,同样永远触发不了更新,最后也保持nil。所以整个reduce返回的就是{:minimum nil, :maximum nil}。
再看第二个reduce的修正逻辑
(reduce (fn [{:keys [minimum maximum]} new-number] {:minimum (if (and minimum (> new-number minimum)) minimum new-number) :maximum (if (and maximum (< new-number maximum)) maximum new-number)}) {} [5 23 5004 845 22])
它把判断逻辑和返回值完全反过来了,刚好解决了初始值为nil的问题:
- 处理
:minimum时,判断条件是(and minimum (> new-number minimum)):第一次minimum是nil,条件不成立,这时候直接返回new-number也就是第一个元素5,这样累加器里的:minimum就有了有效值。后面再处理其他元素时,只要新元素比当前最小值大,就保留原来的最小值;如果更小,就更新为新元素,完美实现了最小值跟踪。 - 处理
:maximum时,判断条件(and maximum (< new-number maximum)):第一次maximum是nil,条件不成立,返回第一个元素5;遇到23时,(and 5 (<23 5))不成立,返回23更新最大值;遇到5004时同理,返回更大的5004,这样就能正确得到最大值了。
总结来说,第一个reduce的逻辑在初始值为nil时完全无法启动更新,而第二个reduce通过反转判断逻辑,在初始阶段就把第一个元素赋值给了min和max,后续的比较才能正常运作~
备注:内容来源于stack exchange,提问作者Antonio Smith
相关产品推荐
相关产品推荐

