Bug #19530
closed`Array#sum` and `Enumerable#sum` sometimes show different behaviours
Description
Hi everyone. 👋🏻
We recently discovered that Array#sum
and Enumerable#sum
will output different results in some edge cases.
Here's the smallest script I managed to write to reproduce the issue:
class Money
def initialize(amount)
@amount = amount.to_f
end
def +(other)
self.class.new(@amount + other.to_f)
end
def to_f
@amount
end
end
p [7.0].each.sum(Money.new(0)) #=> #<Money:0x00000001005b35f0 @amount=7.0>
p [7.0] .sum(Money.new(0)) #=> 7.0 💥
I understand that it is expected that #sum
may not honor custom definitions of the #+
method (particularly when the summed values are Float
).
However, I would like to bring your attention to the fact that, in the example above, calling #sum
on an Array
of Float
values and calling #sum
on an Enumerable
that yields the same Float
values will return results of different types.
I've reproduced the same behaviour with multiple versions of Ruby going from 2.6.5 to 3.2.1.
Ideally, I would expect [7.0].sum(Money.new(0))
to return a Money
object identical to the one returned by [7.0].each.sum(Money.new(0))
.
I think it would make sense if at least they returned an identical value (even if it is a Float
).
Addendum: I forgot to mention this extract of the Array#sum
documentation:
When no block is given, returns the object equivalent to:
sum = init array.each {|element| sum += element } sum
With the example above, it would indeed return a Money
object.