Since Smalltalk-80, sends to #do: have been considered expensive, and sends to #size, inexpensive. And so it has been okay for applications which defined their own Collection subclasses, to add a few milliseconds of cost to something that's already considered expensive (#do:), and not to something which is expected to be fast (#size).
** For 30 years applications were built on these assumptions. Even I did it in Magma. #isEmpty was built on that assumption. Subclass implementors have seemed to agree to these assumptions too, and made their implementations true to them..
May we please reconsider this change?
On Mon, Oct 24, 2016 at 9:07 PM, Chris Muller asqueaker@gmail.com wrote:
Normally its the Subclasses where implementation-specific optimizations are done, not in the top abstractions. At the level of Collection, the code should be elegant, expressive, and defining of the responsibilities by the messages it sends. #size is something of Collection, period, there is nothing wrong with sending it, and checking size = 0 is more elegant than a block activation with non-local return.
As a community that respects its user base, we need to consider the *type* of damage that "Change it!" could cause to existing production applications. These applications were built on the expressive implementation, but now they'll be sending #do: to that SQLCollection instead of #size, which will cause the database to retrieve a full ResultSet, send it back to the client, just so it can answer #isEmpty.
Its this kind of "silent" damage that is the worst. Because its invisible, not a an error, not a blow up. Just an degradation in performance (ironic, given our motive here) which, believably, would not be caught in testing.
I agree with Monty. Collection is abstract, there will never be an instance of it. No self-respecting subclass needs this optimized, and trying to optimize it way up there forces too many assumptions about implementation. It makes the code less expressive while silently inflicting potentially performance-killing pain onto legacy applications until they're forced to sprinkle duplicate #isEmpty implementations all about..
On Mon, Oct 24, 2016 at 3:31 AM, Bert Freudenberg bert@freudenbergs.de wrote:
On Monday, 24 October 2016, monty monty2@programmer.net wrote:
Why not just make #size a subclassResponsibility or add abstract superclasses for lazy or infinite collections that implement #isEmpty using #do: and change #size to shouldNotImplement?
Because #do: is the only method required to be overridden by Collection subclasses. All other methods are implemented in terms of #do:.
So yes, if your Collection subclass has an optimized implementation for #isEmpty, then provide it. That is a small price to pay for making a class work optimally across different code bases.
- Bert -