The basic question for me is, what should #() sum
return. Right now, it is an error, I would very much like that for this common case the result would be 0. There is a lot of power (easy of use) in a unary selector, we should not destroy that with semantics that force a test before using it. If we agree on that, we could change the #sum to | sum sample | self isEmpty ifTrue: [ ^ 0 ]. sample := self anyOne. sum := self inject: sample into: [ :accum :each | accum + each ]. ^ sum - sample And the same for #sum: As for #detectSum: that should be removed I think. > On 01 Dec 2015, at 10:33, Nicolai Hess <nicolaih...@gmail.com> wrote: > > > > 2015-12-01 10:26 GMT+01:00 Sven Van Caekenberghe <s...@stfx.eu>: > > > 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 ? > > wokring with things like Color > > (Color wheel:10) sum "works" > (Color wheel:10) newSum:#yourself " would not work" > > > > > 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 > >>> > >> > >> > > > > >