Hi Eliot, I put a lot of effort to convey these arguments for the betterment of Squeak, I hope you'll oblige this last effort with an open and critical mind..
I don't see any such contract. Collection has a contract; to be fully functional as a collection class the subclass must implement #do:. This is stated; #do: is a subclass responsibility of Collection. I see no stated contract that #isEmpty is implemented in terms of #size.
I said a "sort-of 'contract'", because the problem with this change is more about going against the universal reality of the Smalltalk environment and ecosystem, not against an explicit API contract. I made an explanation of this issue in my earlier post which began with "Since Smalltalk-80, sends to #do: ..."
Given that in Collection #size is implemented in terms of #do:, we are free to implement #isEmpty et al in terms either of #do: or of #size. The new implementation is better for large collections, works for infinite collections, and is hence to be preferred.
If you understood that earlier post, then you understand why I believe we are NOT free to change Collection>>#isEmpty to operate in terms #do:, because we will have surreptitiously changed legacy applications which incur a much heavier cost with the #do: implementation. I provided a very plausible example of this (the SQLCollection) which should not be ignored.
Now, I guess this change *already* did even slow down #isEmpty for some existing classes in the image(!!), to which Nicolas reponded to by copying-and-pasting the old implementation code into multiple classes in order to recover their original performance. Wow.
In exchange for these blemishes, how many classes actually got benefit from inheriting the new implementation?
Collection allSubclasses count: [ : each | (each lookupSelector: #size) methodClass = Collection] "0"
So we're obviously not talking about benefit to any *in-image* kind of Collection, maybe just potential benefit to some... external application's Collection? But while hurting others..? Have we reached a point of enough diminishing returns yet?
The reality is that #size is not only part of Smalltalk's original concept of a Collection since 30 years ago, but is universally expected to be fast, and Smalltalkers write there code under that assumption. That's why the responsibility should be on those unknown *exceptional* subclasses, the InfiniteCollection's or whatever, to deny their #size and provide their alternate #isEmpty's.
Tallying it all up, we've got (-1) potential legacy impacts, (-1) all-new copy-and-pasted code in our core library, just so (+0) some exceptional-case external class MIGHT inherit this faster-for-them implementaiton rather than override it.
I totally understand and agree with the ivory-tower arguments made in favor of this change, its just that in the practical world, it turns out to be a net negative.
Best, Chris