Hi guys,

Collection defines #sum:, #detectSum: and #sumNumbers:, all of which accomplish 
the same (in principal) but with subtle differences:

#sum:
- uses #inject:into: with #anyOne as the injected element and will thus fail 
for empty collections

#detectSum:
- uses “nextValue + sum” instead of “sum + nextValue” which makes it a lot 
slower when dealing with large numbers (primitive fails and number conversion 
is necessary)

#sumNumbers:
- same as #sum but doesn’t fail for empty collections. Only good for numbers 
though.


Benchmarks:

[ 100 timesRepeat: [ (1 to: 1000000) sum: #yourself ] ] timeToRun 18062
[ 100 timesRepeat: [ (1 to: 1000000) detectSum: #yourself ] ] timeToRun 42391
[ 100 timesRepeat: [ (1 to: 1000000) sumNumbers: #yourself ] ] timeToRun 18096



Can we settle for a single implementation? Such as (modified from #sumNumbers:):

newSum: aBlock
        ^ self 
                inject: (self
                        ifEmpty: [ 0 ]
                        ifNotEmpty: [ self anyOne ]) 
                into: [ :sum :each |  sum + (aBlock value: each) ]

This implementation combines the best of the three implementations I think. 
Benchmark:

[ 100 timesRepeat: [ (1 to: 1000000) newSum: #yourself ] ] timeToRun 17955


BTW, there is also the message #sum, which suffers from the same problem as 
#sum: (the implementation is basically a copy). #sum could be implemented as

sum
        ^ self sum: [ :x | x ]


As for the name for the new method, I suggest #sum:.

Cheers,
Max

Reply via email to