Hi Max,

Interesting results...

replacing the #yourself in newSum: cuts the runtime by a factor of two.
using an [:x | x ] block cost 10% compared to a direct version of sum.

So the fastest sum is:

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

And

sum
�� �� ^ self sum: [:x | x ]

is 10% slower.

And

sum
�� �� ^ self sum: #yourself

is 100% slower (i.e. x2)

It may be wise to avoid using #yourself for a block.

Thierry


2015-12-01 9:17 GMT+01:00 Max Leske <maxleske@gmail.com>:
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