Well, I beg to disagree, #sum on an empty collection should return 0.

https://en.wikipedia.org/wiki/Empty_sum

We do not need more tricks, the current trick with #anyOne is more than enough, 
that is not the problem. 

The problem is that it is impossible to talk about sum (in the general most 
common sense) without assuming that the collection should have contained 
numbers, where 0 is the neutral element.

The #anyOne trick solves the problem of the neutral element for non empty 
collection, but leaves it unsolved for empty collections. 

Defining it so that empty collections error is really silly: check the senders, 
most of them are then forced to check before calling #sum. In that case, they 
could all just as well have used #inject:into: for the same amount of code.

> On 28 Dec 2015, at 21:08, Eliot Miranda <eliot.mira...@gmail.com> wrote:
> 
> 
> 
> On Dec 27, 2015, at 1:52 PM, Nicolas Cellier 
> <nicolas.cellier.aka.n...@gmail.com> wrote:
> 
>> 
>> 
>> 2015-12-27 2:49 GMT+01:00 Ben Coman <b...@openinworld.com>:
>> On Sun, Dec 27, 2015 at 6:13 AM, Nicolas Cellier
>> <nicolas.cellier.aka.n...@gmail.com> wrote:
>> >
>> >
>> > 2015-12-25 2:03 GMT+01:00 Eliot Miranda <eliot.mira...@gmail.com>:
>> >>
>> >> Ben,
>> >>
>> >> _,,,^..^,,,_ (phone)
>> >>
>> >> > On Dec 4, 2015, at 12:49 AM, Ben Coman <b...@openinworld.com> wrote:
>> >> >
>> >> >> On Fri, Dec 4, 2015 at 4:23 AM, Nicolai Hess <nicolaih...@gmail.com>
>> >> >> wrote:
>> >> >>
>> >> >>
>> >> >> 2015-12-03 14:48 GMT+01:00 Ben Coman <b...@openinworld.com>:
>> >> >>>
>> >> >>> On Wed, Dec 2, 2015 at 10:45 PM, Sven Van Caekenberghe <s...@stfx.eu>
>> >> >>> wrote:
>> >> >>>>
>> >> >>>>> On 02 Dec 2015, at 15:21, Nicolai Hess <nicolaih...@gmail.com>
>> >> >>>>> wrote:
>> >> >>>>>
>> >> >>>>>
>> >> >>>>>
>> >> >>>>> 2015-12-02 15:03 GMT+01:00 Ben Coman <b...@openinworld.com>:
>> >> >>>>> On Wed, Dec 2, 2015 at 12:38 AM, Tudor Girba <tu...@tudorgirba.com>
>> >> >>>>> wrote:
>> >> >>>>>> Hi,
>> >> >>>>>>
>> >> >>>>>>> On Dec 1, 2015, at 5:13 PM, Max Leske <maxle...@gmail.com> wrote:
>> >> >>>>>>>
>> >> >>>>>>> @Doru
>> >> >>>>>>> You’re missing the point: #anyOne *fails* for empty collections.
>> >> >>>>>>
>> >> >>>>>> I am not missing the point at all. I am saying that if you want
>> >> >>>>>> sum:
>> >> >>>>>> to be generic, it cannot assume a specific Zero object.
>> >> >>>>>>
>> >> >>>>>> And sum: should be generic because of its name.
>> >> >>>>>
>> >> >>>>> I am missing understanding the other use cases.  Can you describe
>> >> >>>>> further the generic nature of #sum & #sum: ?  I would have thought
>> >> >>>>> by
>> >> >>>>> default they only applied to numbers.
>> >> >>>>>
>> >> >>>>> sum can be applied to anything that supports #+, not only numbers
>> >> >>>>> sum: can be applied to any collection with a block that return some
>> >> >>>>> object that supports #+
>> >> >>>
>> >> >>> To me this is a mis-application of polymorphism, that just because
>> >> >>> something responds to #+ it should be summable. We have overloaded the
>> >> >>> semantics of  #+  to mean both numeric addition and
>> >> >>> concatenation/membership, but technically "summation" relates only to
>> >> >>> numeric addition.
>> >> >>
>> >> >>
>> >> >> I didn't wanted to argue for or against any change. I just wanted to
>> >> >> clarify
>> >> >> that there are situations in which a generic sum/sum: that throws an
>> >> >> error
>> >> >> on empty collections and don't assume a null value makes sense.
>> >> >>
>> >> >>
>> >> >>>
>> >> >>>
>> >> >>> https://www.google.com.au/search?q=define+sum&oq=define+sum
>> >> >>>
>> >> >>>
>> >> >>> https://www.google.com.au/search?q=define+concatenate&oq=define+concatenate
>> >> >>>
>> >> >>> For example...
>> >> >>>
>> >> >>> * KMModifier implements  #+  so what is the expected semantic of   " {
>> >> >>> KMModifier shift . KMModifier meta} sum " ?
>> >> >>> To me this is more of a concatenation/join/union facility rather than
>> >> >>> numeric addition.  (btw, that expression actually fails since
>> >> >>> KMModifier does not understand minus #- ) .
>> >> >>>
>> >> >>> * String implements  #+  and  " { '1' . '2' } sum " --> '3',   so
>> >> >>> actually its doing numeric addition.  However  " { 'a' . 'b' } sum "
>> >> >>> produces an error.
>> >> >>>
>> >> >>> So actually there seem some existing problems with summing
>> >> >>> non-numerics.  What examples work?
>> >> >>>
>> >> >>> * Trait classes implement both  #+  and  #- , but the semantic seems
>> >> >>> more to do with membership than numeric addition.  I don't how how to
>> >> >>> produce an example of using #sum against traits.
>> >> >>>
>> >> >>> * Points are summable  " { 2@2 . 3@3 } " --> 5@5.   But then  " 2@2 +
>> >> >>> 1 " --> 3@3   ,   so  " {} sum "  returning  0  would seem to not
>> >> >>> cause any error in this case.
>> >> >>>
>> >> >>>
>> >> >>> cheers -ben
>> >> >>>
>> >> >>>
>> >> >>>>>
>> >> >>>>> therefore you can not assume 0 (<- a number) is a proper initial
>> >> >>>>> value
>> >> >>>>> therefore you *need* to work with #anyOne
>> >> >>>>> and as you can not assume a proper initial value, you can not assume
>> >> >>>>> a
>> >> >>>>> default value for empty collections
>> >> >>>>> -> it should throw an error. If you (the caller of the function)
>> >> >>>>> knows
>> >> >>>>> what to do with an empty collection you have
>> >> >>>>> to check, or call inject:into: directly, with a proper initial
>> >> >>>>> value.
>> >> >>>>
>> >> >>>> I am sorry but I am getting really tired of this, you should read
>> >> >>>> what
>> >> >>>> is being said.
>> >> >>
>> >> >>
>> >> >> do that change, I am not against it. Ben just asked for an example and
>> >> >> I
>> >> >> thought it would be helpful.
>> >> >
>> >> > It was helpful :)  It evolved my thinking.   Now thinking further, I
>> >> > wonder how returning  0  will work with applications using units like
>> >> > Aconcagua, and if it would over-complicate things to do something
>> >> > like...
>> >> >
>> >> >    Collection>>sum
>> >> >       | sum sample |
>> >> >       self isEmpty ifTrue: [ ^ ArithmeticZero ].
>> >> >       sample := self anyOne.
>> >> >       sum := self inject: sample into: [ :accum :each | accum + each ].
>> >> >        ^ sum - sample
>> >> >
>> >> >    ArithmeticZero class >> + anObject
>> >> >        ^anObject
>> >>
>> >> surely you mean
>> >>
>> >> Collection>>sum
>> >>       ^self inject: ArithmeticZero into: [ :accum :each | accum + each ]
>> >>
>> >>    ArithmeticZero class >> + anObject
>> >>        ^anObject
>> >>
>> >> and I'd optimise as
>> >> Collection>>sum
>> >>       | sum |
>> >>       sum := ArithmeticZero.
>> >>       self do: [ :each | sum := sum + each ].
>> >>       ^sum
>> >>
>> >> But in with those that want an error and would use either
>> >> Collection>>sum
>> >>       ^self inject: self anyOne species zero
>> >>                into: [ :accum :each | accum + each ]
>> >>
>> >> or
>> >>
>> >> Collection>>sum
>> >>       | sum |
>> >>       sum := self anyOne species zero.
>> >>       self do: [ :each | sum := sum + each ].
>> >>       ^sum
>> >>
>> >
>> > Not bad, but the class cannot allways determine the correct zero.
>> > For example Matrix is too generic and can't guess about dimensions which 
>> > are
>> > instance specific.
>> > So zero should be instance specific.
>> 
>> So if "species zero" isn't good to implement summing, could we use it
>> to delegate raising an error.
>> For example, cases like Matrix where summing an empty collection
>> should produce an error, this could be done by ArithmeticZero
>> delegating to the second operand to raise the error there?
>> 
>> ArithmeticZero >> + operand
>>     operand species zero + operand
>> 
>> Matrix class >> zero
>>     ErrorZeroDoesn'tMakeSense new signal.
>> 
>> ?
>> cheers -ben
>> 
>> 
>> No, becauseItMakesSenseAtInstanceSide, I'd rather say it like this:
>> if we want to adopt injecting zero into the sum, then let's make it an 
>> instance side message rather than class side.
> 
> +1, so it becomes eg
> 
> Collection>>sum
>        | sum |
>        sum := self anyOne asZero.
>        self do: [ :each | sum := sum + each ].
>        ^sum
> 
> and a Matrix can respond to asZero by answering a suitably dimensioned zero 
> instance.  And if product were implemented, to asUnity with a suitable "one".
> 
>> It's a rather elegant solution, but remember only for a minor problem:
>> - That's only necessary for unordered Collection (since Sequenceable can 
>> just inject self first and start looping at index 2).
>> - And that does not solve the case of empty collections which cannot use 
>> anyOne
> 
> I thought the conclusion was that empty collections /should/ error since the 
> type of zero is undefined.  So if anyOne errors and sum included in its 
> comment an explanation of it being undefined if empty and why then we're good.
> 
>> 
>> Nicolas 


Reply via email to