> On 01 Dec 2015, at 10:18, Ben Coman <b...@openinworld.com> wrote: > > On Tue, Dec 1, 2015 at 4:45 PM, Sven Van Caekenberghe <s...@stfx.eu> wrote: >> I am all for a cleanup, the current situation is confusing. >> The basic #sum should be fast AND work for empty collections with 0 as >> starting element. > >> I know why the #anyOne is used, and that use case should be preserved, but >> it is less common IMHO. > > I'm curious to be learn why?
How many times have you summed a collection of things, where (1) you could not start from the number 0 and (2) the operation was #+ ? Me, never, and if I would need that, I would do an #inject:into: myself. Any counter examples that occur a lot ? > cheers -ben > >> >>> On 01 Dec 2015, at 09:38, Thierry Goubier <thierry.goub...@gmail.com> wrote: >>> >>> 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 <maxle...@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 >>> >> >> >