[squeak-dev] SequenceableCollection #= method in current trunk differs from Squeak 5.2

Nicolas Cellier nicolas.cellier.aka.nice at gmail.com
Wed Jul 1 08:56:58 UTC 2020


Le mer. 1 juil. 2020 à 06:01, Chris Muller <ma.chris.m at gmail.com> a écrit :

> On Tue, Jun 30, 2020 at 7:55 PM Levente Uzonyi <leves at caesar.elte.hu>
> wrote:
>
>> On Tue, 30 Jun 2020, Chris Muller wrote:
>>
>> > Might be worth reopening this discussion.  ANY dependencies on #class
>> seem like a bad thing to me, especially while it's still an in-lined
>> message.  Below is the MC version that did it.  Looks like the time to
>> change this
>>
>> Using #class by default sounds correct to me. If some instances of
>> classes want to be equal to each other, they should handle that
>> themselves by overriding #=.
>>
>
> Because it causes that same undesirable loss of symmetry you mentioned
> about MCVersionName and String, except much worse because it's in a more
> general sense instead of application-specific.  It makes headaches for
> Magma applications because client code has to be aware of it.
>
> Smalltalk wants to be about messages, not types.  What do we need to do to
> make #class non-inlined and therefore overridable?  My impression is that
> this is on the table for 6.0, is it still?
>
>  - Chris
>
>
Hi Chris,
wait a minute, the failure of symmetry of MCVersionName is ABSOLUTELY
UNRELATED to species or class.

There are some wonderful hacks, there are some clever hacks, but at the
end, you very well know that you can cheat as long as you don't get caught.
MCVersionName is not a good hack.

Here we are dressing the String with additional application specific
semantics.
The MCVersionName is a String which knows how to be interpreted in some
context.
There are lot's of contexts where we could dress strings like that, imagine
that we create a DateString, a NumberString...
Should we really do that?
When we do that, we confer more responsibilities to such subclasses. They
are a String, and also more than a String.
But here, the application specific behavior is in contradiction with
superclass, we redefined = with a different behavior.
At the end, we will always get caught with schemes like that, because we
complexify and entangle the concepts.
It seems to me that it's a simple inheritance vs composition anti-pattern.

MCVersion name hash ~= MVVersion name asString hash is a good illustration.
It means that we're breaking a more general contract for implementing our
hack.
It's typical of what will happen by abuse of inheritance.

Think of it, = is a relationship of equivalence. We don't want to loose
that.
So it has to be symmetric, but also transitive:
    String new = StringSubclass1 & ( String new = StringSubclass2 new ) ==>
(StringSubclass1 new = StringSubclass2 new).
That means that we would have accidental equivalence of separate domains if
ever the string representation matches.
That's not what we want.

Also, if StringSubclass1 is more than a String, then how something less
than a StringSubclass1 could be equivalent?
It's not equivalent, it does not behave the same, or we would not need to
subclass in the first place.

Oh but we have String subclasses, ByteString and WideString, so what's the
difference?
The difference is that those are implementation details. They are optimized
internal representations of Strings.
We're not at all after conferring a different behavior, on the contrary.
We absolutely want to confer the same behavior to the outside whatever the
internal representation (class) and try to make them be really equivalent.
Yes, more than often, the implementation details leak out of encapsulation.
It's the problem of tradeoffs between efficiency and universality. We have
to trade some generality for some efficiency.

That's what happens with Interval and Array. They are not equivalent. They
have slightly different behaviors and properties.
An Interval is more than an Array (it has numeric elements with arithmetic
progression).
And it is less than an Array (it cannot at:put: or embed arbitrary objects).
We can casually have an Array carrying the same elements as an Interval,
which can be expressed by #hasEqualElements:

species semantics was overloaded. It did also mean, in which recipient
class should I select:, collect:...
If we use the same recipient for collecting, then we are similar (of same
species)... And if similar, maybe equal?
It might be that Interval was originally seen as an implementation detail,
a (space) optimized version of Array afterall.
But doing so, introduced complexity.
It entangled things.
It broke contracts (hash), or imposed very inefficient implementation of
hash (enumerating all elements of an Interval).
In the end, we get caught, that is carrying more inconvenients than
advantages when trying to sustain the illusion of equivalence.
It's far better and simpler to just abandon the illusion, because it's just
that, a deceitful illusion.

I understand what you mean by abuse of using the class message, we have
somehow lost a hook.
But IMO, this hook was not useful, except for one thing proxy.
We have more than one message in our palette, even if = is a very
convenient symbol (short binary), we cannot dress it with different context
specific meanings, the cheat is getting too apparent.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20200701/9da175fa/attachment.html>


More information about the Squeak-dev mailing list