On Tuesday, May 11, 2021 12:37:20 PM MDT Meta via Digitalmars-d 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.
Having isSomeString accept types that implicitly converted to string would be a disaster. Templates do not operate on implict conversions - or even on subtypes. They operate on the exact type they're given. You can, of course, write a template constraint which checks for implicit conversions, but you still don't get the implicit conversion when the template is instantiated. You get the original type. This has a number of implications, but in general, it leads to bugs if templates check for implicit conversions instead of exact types. In particular, any templated function which checks for an implicit conversion then needs to force the implicit conversion, or it will likely not work properly - be it because you get compilation errors, or because the original type compiles with the same code but does not behave the same way as the type from the implicit conversion which was not actually made.
In fact, IIRC, at one point, isSomeString _did_ work with enums, and we fixed it so that it didn't, because it was causing problems. Also, IIRC, it was my fault that it was ever made to work with enums, and I very much regret that.
In general, implicit conversions have no business in template constraints. Obviously, there are exceptions to that, but in general, there will be fewer bugs if the conversions are done explicitly by the code instantiating the template. The reason that it's done in Phobos as much as it is is primarily because of code that was originally not generic which was later templatized (often because it took string and was changed to work on multiple string types or to work on general ranges of characters). And in most cases where we've tried to templatize functions without breaking code, we've had problems because of the implicit conversions that worked before. std.traits.isConvertibleToString is one such abomination which came out of that (its use usually results in code that slices local variables and escapes them, which is really bad). IIRC, that was done by Walter, and if he's making mistakes like that with regards to implicit conversions and templated code, what do you think the average D programmer is doing?
The main reason for bringing up popFront and enums is to show that that enums with a base type of string are not actually strings, and treating them as if they were causes serious problems. There are of course places where that sub-typing results in implicit conversions, but templates do not work that way, and trying to force it is very problematic. The proliferation of template constraint and static if complexity that Andrei is complaining about with regards to stuff like format is the result of that, and it's the kind of code that's very hard to get right. Simply not trying to support those implicit conversions with templated functions _significantly_ reduces the complexity of such code with the only cost being that the code instantiating the template will have to use cast(string) on the enum value.
- Jonathan M Davis
|