[Cuis-dev] Missing ifEmpty: variants for collections

Juan Vuletich juan at cuis.st
Thu Sep 24 07:42:22 PDT 2026


Hi Facundo,

Thanks for this contribution!

Comments inline.

On 2026-09-21 8:35 PM, Facundo Javier Gelatti via Cuis-dev wrote:
> Hello!
>
> I attach a change set to add some useful methods to the collections. 
> In particular, missing "ifEmpty" cases, like #sumIfEmpty: or 
> #max:ifEmpty:. I also attach another change set for the 
> CollectionsTests package, to add some tests for these changes.

I don't think all this messages carry their weight. I don't think all 
them should be included in the Cuis base image only for completeness. 
The already existing ones are #average:ifEmpty:, #sum:ifEmpty: and 
#lastIfEmpty: It can be argued that these are useful and they already 
have users. I pushed your updated comments, though. I also included your 
#firstIfEmpty: because #lastIfEmpty: is already there, and those belong 
together.

> Here I leave some notes regarding the changes, to help during the review:
> * For the message #anyOne, the raised exceptions are different now. 
> For example, "(1 to: 0) anyOne" used to raise "subscript is out of 
> bounds: 1", and now raises "this collection is empty" (the same thing 
> happens to "RunArray new anyOne"). I think this is an improvement, 
> although I mention it explicitly just in case.

Agreed!

> * One case we should validate is with Heap, because "Heap new anyOne" 
> used to return "nil", but now raises "this collection is empty". As 
> the size of the heap is 0 and #isEmpty returns true, I think the 
> change is in the correct direction.

Yes. Agreed.

> * I followed the convention of evaluating "emptyBlockOrValue 
> valueWithPossibleArgument: self" in the empty cases, like 
> Collection>>#ifEmpty: does. This sometimes changes the behavior a bit, 
> by being more permissive. For an interesting case regarding this, see 
> for example the change in #average:ifEmpty:.

I don't agree with this take. Sending #valueWithPossibleArgument: is ok 
for some methods, but in particular #average:ifEmpty:, #sum:ifEmpty:, 
#firstIfEmpty: and #lastIfEmpty: should not modify the receiver. They 
are for a "Functional Like" code style. Code needing to modify the 
collection should do it in a more clear and explicit way, for instance:
     aCollection
         ifEmpty: [ "modify aCollection in any way" ]
         ifNotEmpty: [ aCollection sum: [:xx | xxx ... ] ]

> * I found that Collection>>#max: and #min: skip leading nils. For 
> example: "#(nil 3) max: [:x | x]" answers 3, but "#(3 nil) max: [:x | 
> x]" raises an exception. The code is very explicit about this, so I 
> guess this is (or at some point was) the expected behavior. I left 
> this behavior as it was, but I'm curious if this is something that 
> could be simplified (my expectation would have been for both examples 
> to raise an exception). On the other hand, in case it's needed, it'd 
> be nice to have at least one test documenting it.

I don't think this is the intended behavior at all! This is a bug to me. 
Pushed a separate change to address this. BTW, the reason to use 
separate changesets is to ease debugging and fixing in case any of the 
assumptions made turns out to be wrong, and something breaks. Small 
changes are so much easier to spot and fix in the future.

> * I left the cases where nil is returned by default as they are (e.g. 
> #detectMax:/#detectMin:), because I'm thinking of this as a change 
> closer to a refactor. But we might consider revisiting those defaults, 
> and make them raise an exception instead, to be consistent with what's 
> done in other cases.

I agree it is not consistent with other cases. But it is stated in the 
method comment. So it is the current contract. We'd need to assess 
consequences before changing that.

>
> Cheers!
> Facu
>
Again, Thanks!

Cheers,

-- 
Juan Vuletich
www.cuis.st
github.com/jvuletich
researchgate.net/profile/Juan-Vuletich
independent.academia.edu/JuanVuletich
patents.justia.com/inventor/juan-manuel-vuletich



More information about the Cuis-dev mailing list