Feature #12902
closedHow about Enumerable#sum uses initial value rather than 0 as default?
Description
In https://bugs.ruby-lang.org/issues/12217#note-3, Akira Tanaka, mentions that the default argument to sum is 0. This creates problems with non-numeric summations (e.g. strings). This would make the method more flexible. It also makes it behave more like reduce. I think using the initial value in the enumerable is less surprising than using 0.
Updated by AaronLasseigne (Aaron Lasseigne) almost 10 years ago
In https://bugs.ruby-lang.org/issues/12217#note-3, Akira Tanaka, mentions that the default argument to sum is 0. This creates problems with non-numeric summations (e.g. strings). I would like to suggest using the first enumerable value. This would make the method more flexible. It also makes it behave more like reduce. I think using the initial value in the enumerable is less surprising than using 0.
** I missed a sentence. :( **
Updated by akr (Akira Tanaka) almost 10 years ago
- Status changed from Open to Feedback
I think [].sum should return 0.
Returning 0 is better than nil because programmers don't need to treat empty array specially.
This behavior is different with Enumerable#reduce which returns nil for empty array.
Also, string summation using Enumerable#sum is not good idea because it is slow.
String#join is faster.
So, we should not encourage Enumerable#sum for string summation.
Updated by duerst (Martin Dürst) almost 10 years ago
On 2016/11/05 04:28, aaron.lasseigne@gmail.com wrote:
Issue #12902 has been updated by Aaron Lasseigne.
In https://bugs.ruby-lang.org/issues/12217#note-3, Akira Tanaka, mentions that the default argument to sum is 0. This creates problems with non-numeric summations (e.g. strings). I would like to suggest using the first enumerable value. This would make the method more flexible. It also makes it behave more like reduce. I think using the initial value in the enumerable is less surprising than using 0.
What would/should the behavior be for an empty array?
Updated by herwin (Herwin W) almost 10 years ago
Akira Tanaka wrote:
I think [].sum should return 0.
Returning 0 is better than nil because programmers don't need to treat empty array specially.
This behavior is different with Enumerable#reduce which returns nil for empty array.Also, string summation using Enumerable#sum is not good idea because it is slow.
String#join is faster.
So, we should not encourage Enumerable#sum for string summation.
I guess you mean Array#join
And the fact that Enumerable#sum could be used for string concatenation makes the default value of 0 pretty weird. Just imagine the following piece of code:
This just removes the special case of empty arrays for numeric values, but still doesn't help much with anything else (even though I agree that calculating a sum of strings is just stupid)
Updated by AaronLasseigne (Aaron Lasseigne) almost 10 years ago
Martin,
I would expect the empty to act like reduce and return nil.
Akira,
I agree that doing string concatenation with sum is a poor idea. It's just that this is on Enumerable which is supposed to allow iterations over whatever underlying data you want and this is favoring a particular type of underlying data. I do understand that 0 is convenient for the vast majority of use cases, it just feels like Numeric is creeping into Enumerable.
Thanks for considering it and responding.
Updated by bitsweat (Jeremy Daer) almost 10 years ago
If we treated the first argument to #sum as the additive identity instead of "initial element," then it'd be very clear what to expect:
When there are no elements in the Enumerable, return the identity.
That works nicely for summing non-numeric/string/etc objects:
Plus, it's backward compatible, doesn't break existing behavior.
Updated by akr (Akira Tanaka) almost 10 years ago
- Status changed from Feedback to Rejected
Jeremy Daer wrote:
If we treated the first argument to
#sumas the additive identity instead of "initial element," then it'd be very clear what to expect:
I like current behavior than yours because the behavior can be explained simpler:
Enumerable#sum returns initial + elem0 + elem1 + ... elemN.
No need to distinguish empty and non-empty enumerable.
Yours needs more complex explanation.
Plus, it's backward compatible, doesn't break existing behavior.
Enumerable#sum and Array#sum is defined in many gems with different behaviors.
Perfect backward compatibility is impossible.
Updated by ioquatix (Samuel Williams) over 9 years ago
Just to add, this breaks code which uses facets.
https://github.com/rubyworks/facets/issues/247
The method signature is:
I think it's probably important to consider this use case.