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
> >>>
> >>
> >>
> >
> 
> 
> 


Reply via email to