<div dir="ltr">Hi Nicolas,<div><br></div><div>Yes, I understand.  For general classes, it's impossible to tolerate non-symmetry.  This is an outward-looking tool that didn't need that contract, and took advantage of legacy backward-compatibility via inheritance rather than composition.  An encapsulating pointer object would be less efficient (a bunch of extra objects + GC), and face the very same equivalence problem due to Squeak not letting client code define symmetrical equivalence in their subclasses.  The fault is not with MCVersionName, it's with our core library.</div><div><br></div><div>Q:  What does #= have in common with #+, #-, #*, #/  ?   </div><div>A:  It wants to be able to interoperate with different <span style="text-decoration-line:underline">classes</span> for the <i>lvalue</i> and <i>rvalue</i>.  That's why the latter four all double-dispatch.  The same applies to #=, the only difference is its "calculation" result is a boolean type instead of some Number.</div><div><br></div><div>So why can't we double-dispatch with #=, too?  Or, maybe we can simply dispatch.  To #sameTypeAs:?</div><div><br></div><div>   Object>>#sameTypeAs: anObject</div><div>      "Answer whether the receiver is regarded as the same type as anObject."</div><div>      ^ self class = anObject class</div><div><br></div><div>(we may need a double-dispatch, but... that's just details)</div><div><br></div><div>Interested in your thoughts on the hard type-checking.  Observe how String>>#= got a pass that no one else got.  Because it was convenient, and because we, the great developers, have full control, we softened it, let it rely on #isString rather than the hardass draconian type-test (via an inlined message even!).  But that reveals the limitation, *users* don't have that luxury.  They aren't able to make anything similar for <u>any</u> subclass and still maintain symmetric equivalence.</div><div><br></div><div>IMO, all this hard type-checking is crippling Squeak's wish to be more dynamic.  Magma, too.  It could be so great if we would just <u>let</u> it.  Would you be open to double-dispatching for #= as with the other binary operators?</div><div><br></div><div>Regards,</div><div>   Chris</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 1, 2020 at 3:57 AM Nicolas Cellier <<a href="mailto:nicolas.cellier.aka.nice@gmail.com" target="_blank">nicolas.cellier.aka.nice@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le mer. 1 juil. 2020 à 06:01, Chris Muller <<a href="mailto:ma.chris.m@gmail.com" target="_blank">ma.chris.m@gmail.com</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr">On Tue, Jun 30, 2020 at 7:55 PM Levente Uzonyi <<a href="mailto:leves@caesar.elte.hu" target="_blank">leves@caesar.elte.hu</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">On Tue, 30 Jun 2020, Chris Muller wrote:<br>
<br>
> 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<br>
<br>
Using #class by default sounds correct to me. If some instances of <br>
classes want to be equal to each other, they should handle that <br>
themselves by overriding #=.<br></blockquote><div><br></div><div>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.</div><div><br></div><div>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?</div><div><br></div><div> - Chris<br></div></div></div>
<br></blockquote><div><br></div><div>
<div>Hi Chris,</div><div>wait a minute, the failure of symmetry of MCVersionName is ABSOLUTELY UNRELATED to species or class.</div><div><br></div><div>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.</div><div>MCVersionName is not a good hack.</div><div><br></div><div>Here we are dressing the String with additional application specific semantics.</div><div>The 
MCVersionName is a String which knows how to be interpreted in some context.<br></div><div>There are lot's of contexts where we could dress strings like that, imagine that we create a DateString, a NumberString...</div><div>Should we really do that?</div><div>When we do that, we confer more responsibilities to such subclasses. They are a String, and also more than a String.</div><div>But here, the application specific behavior is in contradiction with superclass, we redefined = with a different behavior.<br></div><div>At the end, we will always get caught with schemes like that, because we complexify and entangle the concepts.</div><div>It seems to me that it's a simple inheritance vs composition anti-pattern.<br></div><div>
<div><br></div><div>MCVersion name hash ~= MVVersion name asString hash is a good illustration.<br></div><div>It means that we're breaking a more general contract for implementing our hack.</div><div>It's typical of what will happen by abuse of inheritance.<br></div>

</div><div><br></div><div>Think of it, = is a relationship of equivalence. We don't want to loose that.</div><div>So it has to be symmetric, but also transitive:<br></div><div>    String new = StringSubclass1 & (
String new = StringSubclass2 new

) ==> (StringSubclass1 new = StringSubclass2 new).</div><div>That means that we would have accidental equivalence of separate domains if ever the string representation matches.</div><div>That's not what we want.</div><div><br></div><div>Also, if StringSubclass1 is more than a String, then how something less than a 
StringSubclass1 could be equivalent?</div><div>It's not equivalent, it does not behave the same, or we would not need to subclass in the first place.</div><div><br></div><div>Oh but we have String subclasses, ByteString and WideString, so what's the difference?</div><div>The difference is that those are implementation details. They are optimized internal representations of Strings.
<div>We're not at all after conferring a different behavior, on the contrary.</div>

</div><div>We absolutely want to confer the same behavior to the outside whatever the internal representation (class) and try to make them be really equivalent.</div><div>Yes, more than often, the implementation details leak out of encapsulation.</div><div>It's the problem of tradeoffs between efficiency and universality. We have to trade some generality for some efficiency.<br></div><div><br></div><div>That's what happens with Interval and Array. They are not equivalent. They have slightly different behaviors and properties.</div><div>An Interval is more than an Array (it has numeric elements with arithmetic progression).</div><div>And it is less than an Array (it cannot at:put: or embed arbitrary objects).</div><div>We can casually have an Array carrying the same elements as an Interval, which can be expressed by #hasEqualElements:

</div></div><div><br></div><div><div>species semantics was overloaded. It did also mean, in which recipient class should I select:, collect:...</div><div>If we use the same recipient for collecting, then we are similar (of same species)... And if similar, maybe equal?
<div>
<div>It might be that Interval was originally seen as an implementation detail, a (space) optimized version of Array afterall.</div></div>

</div><div>But doing so, introduced complexity.</div><div>It entangled things.</div><div>It broke contracts (hash), or imposed very inefficient implementation of hash (enumerating all elements of an Interval).</div><div>In the end, we get caught, that is carrying more inconvenients than advantages when trying to sustain the illusion of equivalence.<br></div><div><div></div>

</div><div>It's far better and simpler to just abandon the illusion, because it's just that, a deceitful illusion.<br></div><div><br></div><div>I understand what you mean by abuse of using the class message, we have somehow lost a hook.</div><div>But IMO, this hook was not useful, except for one thing proxy.<br></div><div>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.<br></div><div><br></div> 

<br></div></div></div>
<br>
</blockquote></div>