No we should not support enum types derived from strings
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Tue May 11 21:36:46 UTC 2021
On 5/11/21 2:37 PM, Meta wrote:
> On Tuesday, 11 May 2021 at 16:44:03 UTC, Andrei Alexandrescu wrote:
>>> Again with moving the goalposts.
>>
>> To clarify: you can't make up your own definitions as you go so as to
>> support the point you're making at the moment. You can't go "oh, call
>> it something else than a type, my point stays". No. Your point doesn't
>> stay.
>>
>> By the same token you can't make up your own definition of what
>> subtyping is and isn't. Value types and reference types are
>> well-trodden ground. You can't just claim new terminology and then
>> prove your own point by using it.
>
> I apologize for injecting myself into this conversation, but with all
> due respect, what the hell are you talking about? Everything Deadalnix
> is saying makes perfect sense - it's basic type theory, and yet you're
> accusing him of moving goalposts and making up definitions, etc. The
> problem is that `isSomeString` doesn't respect the LSP and the template
> constraints on the relevant stdlib functions for enums are a hack to
> work around that. End of story. if `isSomeString` was defined sensibly,
> these template constraint hacks would not have to exist.
>
> All the bluster about `popFront` on enum strings, etc. is completely
> irrelevant, and is a red herring anyway (as was already explained).
>
> I'm sorry for being so blunt, but this conversation is painful to read.
Being blunt is totally cool, but that doesn't make you right.
There's no true subtyping or polymorphism with value semantics. This has
been common knowledge in C++ - inheriting a value type is an antipattern
for many reasons, and conversion operators are to be used carefully (and
not as a substitute to subtyping) for many other reasons.
With value types, it's all static typing, no polymorphism, no LSP beyond
what's called ad-hoc polymorphism in the classic Caderlli et al paper
(http://poincare.matf.bg.ac.rs/~smalkov/files/old/fp.r344.2016/public/predavanja/FP.cas.2016.07%20-%20p471-cardelli.pdf).
What can be aimed for with values is called "parametric polymorphism"
(which is NOT subtyping) by the same paper: "Parametric polymorphism is
obtained when a function works uniformly on a range of types; these
types normally exhibit some common structure."
That works if and only if you can reasonably supplant the same
primitives across said range of types. With enums that's onerous; as
soon as you "derive" an enum from int you figure that ++x can't
reasonably be implemented. Same goes for enum strings - you can't
implement the expected string primitives so substitutability is out the
window.
Values are monomorphic. Years ago I found a bug in a large C++ system
that went like this:
class Widget : BaseWidget {
...
Widget* clone() {
assert(typeid(this) == typeid(Widget*));
return new Widget(*this);
}
};
The assert was a _monomorphism test_, i.e. it made sure that the current
object is actually a Widget and not something derived from it, who
forgot to override clone() once again.
The problem was the code was doing exactly what it shouldn't have, yet
the assert was puzzlingly passing. Since everyone here is great at
teaching basic type theory, it's an obvious problem - the fix is:
assert(typeid(*this) == typeid(Widget));
Then the assertion started failing as expected. Following that, I've
used that example for years in teaching and to invariably there are eyes
going wide when they hear that C++ pointers are monomorphic, it's the
pointed-to values that are polymorphic, and that's an essential
distinction. (In D, just like in Java, classes take care of that
indirection automatically, which can get some confused.)
More information about the Digitalmars-d
mailing list