> On 04 Dec 2015, at 01:49, Ben Coman <b...@openinworld.com> wrote: > > On Fri, Dec 4, 2015 at 4:23 AM, Nicolai Hess <nicolaih...@gmail.com > <mailto: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 agree. If I want to sum something other than a collection of numbers I’ll happily provide the block for that summation (I wouldn’t even expect strings to be summable to be honest. Why would you have a collection of numbers that are strings…? And if you really have one, you should convert it explicitly so that another person reading your code knows what’s going on.) >> >> >> 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 While I think you might be on to something, I think we should take small steps. I’d be happy already if we can just get rid of one superfluous method and provide a better API without starting to think about the deeper semantics. Also, I think there’s a reason why Aconcagua is an external package: developers usually are happy to work with numbers (which are already objects in Smalltalk anyway) and they’re fast. > > cheers -ben > >> >> >>> >>>> >>>> I am not suggesting to stop using #anyOne because I like why it is there >>>> and what it can do. >>>> >>>> The change I want is what happens with an empty collection when using >>>> the simplest selector, #sum. >>>> >>>> I do not want to say to some collection of numbers #sumIfEmpty: [0], >>>> because summing numbers starting from zero is the most common case and >>>> everybody expects that, hence the unary selector fits. >>>> >>>> I want the less common cases to use the more complicated API, as in some >>>> collection of colors #sumIfEmpty: [ Color black ] >>>> >>>> In my book that is common sense API design. >>>> >>>> Doing that I do no take anything away, because today you already have to >>>> make sure the collection is not empty. >>>> >>>> The only change would be in the error behaviour. I think that is a >>>> reasonable price to pay. Instead of having #anyOne fail, it will say that >>>> #+ >>>> cannot add 0 to some object, and in a comment we can point to the >>>> alternative API. >> >> >> >> >>> >>>> >>>> http://izquotes.com/quote/242740 right ? >>>> >>>>> cheers -ben >>>>> >>>>>> >>>>>>>> On 01 Dec 2015, at 15:31, Esteban A. Maringolo >>>>>>>> <emaring...@gmail.com> wrote: >>>>>>>> >>>>>>>> I don't want to be heretic (or too orthodox), but why not to >>>>>>>> delegate >>>>>>>> this behavior to other class (an iterator maybe?). >>>>>>>> >>>>>>>> It's too tempting adding these convenience methods to Collection >>>>>>>> and/or subclasses, but anything that requires an explicit protocol >>>>>>>> of >>>>>>>> its elements is wrong, IMO. >>>>>>>> >>>>>>>> something like aCollection arithmetic sum: [...] or.... aCollection >>>>>>>> arithmetic avg. > > > On Fri, Dec 4, 2015 at 3:26 AM, Chris Cunningham > <cunningham...@gmail.com <mailto:cunningham...@gmail.com>> wrote: >> <uncontrolled snipping> >> >> On Thu, Dec 3, 2015 at 5:48 AM, Ben Coman <b...@openinworld.com >> <mailto:b...@openinworld.com>> wrote: >>> * 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. >> >> but points aren't commutative: >> >> 2@2 + 1 " = 3@3" >> 1 + 2@2 " = 3@2" >> >> Of course, 0 wouldn't be an issue, unless you wanted to access x or y!