Bug #13700
closedEnumerable#sum may not work for Ranges subclasses due to optimization
Description
Enumerable#sum
is optimized for integer ranges. Unfortunately, this can break subclasses:
class StepTwoRange < Range
def each(&block)
step(2, &block)
end
end
r = StepTwoRange.new(0, 10)
r.to_a #=> [0, 2, 4, 6, 8, 10]
r.to_a.sum #=> 30
r.sum #=> 55
The optimization should therefore only be triggered for instances of Range
and not for instances of subclasses. (or more specifically, not for subclasses overriding each
)
If this behavior is intentional, it should at least be documented.
Updated by sos4nt (Stefan Schüßler) almost 8 years ago
- Description updated (diff)
Updated by sos4nt (Stefan Schüßler) almost 8 years ago
- Description updated (diff)
Updated by shevegen (Robert A. Heiler) almost 8 years ago
Reminds me a bit of what hanmac wrote elsewhere; I can't find it right now and forgot it mostly already but I think he also mentioned some unexpected behaviour when ... subclassing I think? Or some custom class that he wrote...
Updated by Hanmac (Hans Mackowiak) almost 8 years ago
shevegen (Robert A. Heiler) wrote:
Reminds me a bit of what hanmac wrote elsewhere; I can't find it right now and forgot it mostly already but I think he also mentioned some unexpected behaviour when ... subclassing I think? Or some custom class that he wrote...
my comment was for https://bugs.ruby-lang.org/issues/13663
with String#upto you can't overwrite the internal String#<=>
Updated by sos4nt (Stefan Schüßler) almost 8 years ago
Side note: in my opinion, Enumerable
should not check the receiver's class to provide specific optimizations. Instead, Range
should override sum
and handle the optimization itself. Range#sum
would also be a better place to document this behavior. (it still doesn't solve the subclassing issue, though)
Updated by jeremyevans (Jeremy Evans) over 5 years ago
- Status changed from Open to Closed
Applied in changeset git|e496e96547b64c3a2fa6f285c3bc9bd21a245ac6.
Document that Enumerable#sum may not respect redefinition of Range#each
It already documented that it may not respect redefinition
of Integer#+.
Fixes [Bug #13700]