I did a pass on all the changes that would be required (whatever the outcome of this discussion). Looks easy enough. One interesting point: FloatArray>>sum is implemented as a primitive in the FloatArrayPlugin and the zero element is explicitly defined as 0.0. The primitive will not fail for an empty collection but return 0.0. That would be in line with our new definition of #sum. One other thing: should the old selectors be marked as deprecated rather than being removed? I think thatâs the general policy, right? Cheers, Max
On 20 Dec 2015, at 18:19, Max Leske <maxleske@gmail.com> wrote:
On 20 Dec 2015, at 15:26, Ben Coman <btc@openInWorld.com <mailto:btc@openinworld.com>> wrote:
On Mon, Dec 21, 2015 at 12:43 AM, Sven Van Caekenberghe <sven@stfx.eu <mailto:sven@stfx.eu>> wrote:
Doru,
For me this whole discussion started because you (the standpoint that you take) hijacked the best selector (#sum) for a use case that is much less common than adding a collection of numbers which should give 0 when empty (you hijack it by not wanting to return 0, which I totally understand, but doing so you redefine the meaning/semantics).
Max's point is to make everything more consistent and remove some API. I support that too.
Now, I like Max's proposal.
But, you know, my conclusion when the thread ended was that it might be better to throw all these selectors away, since #inject:into: covers most use cases at least as well and at least as clear.
Sven
On 20 Dec 2015, at 14:10, Tudor Girba <tudor@tudorgirba.com <mailto:tudor@tudorgirba.com>> wrote:
Hi,
Could we not have sum, but sumNumbers instead? So, we would end up with:
sum:ifEmpty: sum: (with error) sumNumbers (without error)
From the outside, #sum: looks like it should parameterize #sum, but the implementation is actually different. So, given that in this implementation #sum is not a special case of #sum: the two should be named differently to reflect that difference. Hence my proposal is to keep #sumNumbers instead of #sum.
I agree somewhat with Duro to avoid #sum and #sum: having different semantics, but I agree more with Sven about keeping #sum for numbers only and returning zero, so why not turn Doru's suggestion around...
#sum (empty --> 0) #sumBy: (empty --> error) #sumBy: ifEmpty: (empty --> no error)
alternatively could be #sumUsing: or #sumWith: or something similar.
Also a good idea. However, looking at the methods on Collection, the pattern is usually #message and #message:, e.g. #sorted and #sorted:. There used to be #sortBy: but it was removed because the view was that the protocol semantics should be the same across all methods. The current case is a bit different of course since weâre dealing with the problem of the zero element which doesnât arise in most other cases. Still, I think from a users point of view it would be strange to have to use #sumBy: when every other message pair uses the #message / #message: pattern.
I feel that this argument (thanks Ben :) ) is also a valid point against Doruâs argument for #sumNumbers. While #sumNumbers may *technically* be the best name (which we canât seem to agree onâ¦), #sum, #sum: and #sum:ifEmpty: form a triple that naturally fits into the naming protocol applied elsewhere.
Cheers, Max
Cheers, Doru
On Dec 20, 2015, at 1:47 PM, Max Leske <maxleske@gmail.com <mailto:maxleske@gmail.com>> wrote:
On 20 Dec 2015, at 13:43, Gabriel Cotelli <g.cotelli@gmail.com <mailto:g.cotelli@gmail.com>> wrote:
Max,
sum: aBlock ifEmpty: emptyBlock needs to obtain the sample evaluating the block.
sum: aBlock ifEmpty: emptyBlock | sum sample | self isEmpty ifTrue: [ ^ emptyBlock value ]. sample := aBlock value: self anyOne. sum := self inject: sample into: [ :accum :each | accum + (aBlock value: each) ]. ^ sum - sample
Thanks! Missed that.
On Sun, Dec 20, 2015 at 8:59 AM, Max Leske <maxleske@gmail.com <mailto:maxleske@gmail.com>> wrote: I would like to wrap up this discussion.
On 05 Dec 2015, at 18:14, stepharo <stepharo@free.fr <mailto:stepharo@free.fr>> wrote:
So what is the conclusion? I like the idea of Esteban M to have iterator because it moves some behavior out of core classes.
[[[
aCollection arithmetic sum: [...] or.... aCollection arithmetic avg.
]]]
While I think that iterators are an intriguing idea I also believe that they are beyond the scope of this issue. If anybody wants to follow up on iterators (or unit types for that matter) please start a new thread / issue.
I propose to use Svenâs version for #sum:ifEmpty:. The result would be these three methods:
sum ^ self sum: [ :each | each ] ifEmpty: [ 0 ]
sum: aBlock ^ self sum: aBlock ifEmpty: [ self errorEmptyCollection ]
sum: aBlock ifEmpty: emptyBlock | sum sample | self isEmpty ifTrue: [ ^ emptyBlock value ]. sample := self anyOne. sum := self inject: sample into: [ :accum :each | accum + (aBlock value: each) ]. ^ sum - sample
Iâve attached a couple of benchmark results below. To me they show that 1. the new implementation is maybe a tiny bit slower but insignificantly so (if youâre going for performance youâll probably write your own optimised version anyway) 2. there is no need to duplicate the code (like #sum and #sum: currently do). Itâs perfectly fine to delegate to #sum:ifEmpty:
In addition to the above changes I would like to remove #detectSum: (-> #sum:) and #sumNumbers (-> #sum).
Note that once we agree on changing this API, we will need to also change #detectMin:, #detectMax:, #min, #max as well as all overrides (e.g. RunArray, Interval) of these and of #sum et. al. to stay consistent. The changes would of course be in line with this change, such that every operation has a unary selector with a sensible default, one that takes a block and throws an error for empty collections and a third that takes a block for the iteration and one for the empty case.
Please cast your vote for these changes:
1. Do you agree to changing #sum and #sum: in the suggested way?
yes
2. Do you agree to the removal of #detectSum:? ?? (not familiar)
3. Do you agree to the removal of #sumNumbers? yes
4. Do you agree that the #max and #min selectors also need to be adapted? ?? (not familiar)