[swift-evolution] Proposals: (1) Forbidding custom `==` for value types, (2) `dispatch` keyword, (3) `default`-result for methods with `Self`, and (4) Poor-Mans-Existentials
Félix Cloutier
felixcca at yahoo.ca
Mon Jul 18 23:29:01 CDT 2016
>>
>>> 1. You cannot say something is unequal although the system says it is equal
>>
>> That doesn't make me feel much safer. Comparison returned false when it should have returned true?
>
> Yes you just may have a condition inverted e.g.. You could even have a compiler flag, where you remove the short-circuit and throw an error, if you have a false-negative. This would ease finding such issues (easier than just not having this feature)
This minor enhancement could most likely be obtained by just having a default ==, which is a project that I can get behind.
>
>> Step into, see why it happened. Sounds like your garden variety of bugs. The downside is that every comparison now starts with an equality comparison of every field, which is not obvious (you can't step into invisible behavior), and does more work than necessary.
>
> There could again be compiler optimizations, that skip this check (in a given mode), but I don’t think in the future this won’t be necessary anymore:
> * For small value types the comparison will be very fast.
> * For bigger values I hope for such a unique value pool (with copy-on-write) which can be checked with a simple reference comparison (very cheap, very fast).
The fact that the mandatory memberwise comparison would be "fast" is no excuse for the fact that if it doesn't hit but the structures are still equal, you're possibly *doubling* the time that it takes to check.
Also, what about C structures with character arrays? They get translated as tuples of CChar (if that's what they're still called now, didn't really keep track). The two are equal as soon as you hit a null terminator, but memberwise comparison doesn't know that.
> Invisible behavior is everywhere: Automatic Reference Counting, Existential Containers, Virtual Functions, …
>
> Swift is a high-level language, so it’s main appeal is invisible behavior, but I would call it *rich semantics* or something like that.
There is an actual demand for these. With ARC, I don't need to think about memory management (too much). Virtual functions let me implement OO design, which allows a ton of developers to leverage experience. With forced memberwise comparisons, I can trade easily debuggable problems for surprising behavior.
Also keep in mind that most of these things are criticized to some degree. ARC is a common enough source of bugs that Apple has a relatively large investment into tools specially made to debug them. OO also has a ton of detractors.
>>> 2. You do not have to implement equality for value types, only if you really need custom behavior (so you do not write boiler-plate code, which is error prone), so side effects will be less common
>>
>> I think that a default == for structs that only have Equatable fields makes sense and I can get behind that. We don't need the rest to implement this, though.
>
> The default implementation should definitively not call == on properties to reference types conforming to equatable (by default), since this means that the standard semantics of equality of structs is prone to race conditions. This should be something, that a user can do in a custom implementation, if he really needs to and then he should consider using a synchronous dispatching queue using GCD.
I don't care a lot how a default == would be implemented if we had one, as long as it made some sense. I'm sure that the community would come together and nitpick every last wrinkle out of the correct implementation. I'd be happy to have one, that's the main point.
>>> 4. With `dispatch` in operator-methods (or any other) as well as a `default` clause for reference types, so that equality of mixed-types just result in `false`, so that this is not possible anymore (see excerpt of discussion):
>>
>> If I understand the suggested dispatch keyword correctly, it could only work if executables carried metadata for every method,
>
> It is like a virtual method, but for arbitrary parameters, so you need some kind of V-table for that and a lookup, that can be done in constant time. It is something, that I wouldn’t add by default. It is something that you may add to a method explicitly via a keyword (instead of implementing the dynamic dispatch by hand, by calling an `equals:other` method on the left-hand-side and then doing an if-cascade for rhs for example; which is error-prone). So you may use it wisely only, where necessary (and the internal implementation of swift will be much faster, than the manual variant). The XTend language has such a feature.
I didn't understand what you meant with dispatch. Now, my understanding is that it would be used to implement virtual dispatch over multiple parameters (instead of just `self`). I can see uses for that, and I can see that it doesn't need as much metadata. I could agree to that feature independently.
>> You are imposing the costs not just upon yourself, but upon everybody, on every platform, on every project, forever. Would it be a web app or an operating system component, the only way to opt out is to stop using the default equality and fragment the way that you do comparison. Are you really that confident that this will make everyone happier, now and in the future, than the model that we currently have?
>
> My proposals are just additions, they are not forcing to do anyone anything. They just help to reduce bugs and to have more intuitive (visible) behavior of methods via dynamic dispatch where it is needed.
What? You want to force every equality check to start with a memberwise comparison of *everything*.
>> Please realize that this is an absolutely radical change. Swift currently has little to no invisible behavior, and currently lets you implement equality any way that you like. In my book, radical changes should be considered with extreme skepticism, and should have an extremely compelling case behind them.
>
> First off, I don’t think, that the changes are that radical and second this example gives a small insight how bad you can implement equality in swift:
None of it is hard enough to debug to justify a performance hit. Just because you're able to misuse a feature is not an argument that this feature shouldn't be available, especially if you can only half-solve the problem.
Why can't you be content with a default implementation? People all over are saying "don't touch my code", there's a very easy way to not touch anyone's code, but it's like you really want to.
Félix
More information about the swift-evolution
mailing list