www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What did you think about an implicitConversionOp ?

reply sighoya <sighoya gmail.com> writes:
I like the idea of an `implicitConversionOp` or 
`implicitCoercionOp` more than multiple alias this since the 
operator is separated from the source type.

It was already proposed here: 
https://forum.dlang.org/post/qdwiajtugvqpdlyvbvda forum.dlang.org

But I think to mitigate Walther's main concerns about multiple 
inheritance, we need to adapt D's overload resolution to support 
specialization on concrete types:

1.) Best match
2.) Inferring an order of methods regarding implicit conversions 
if possible

What is your opinion regarding this?
Dec 26 2020
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 26 December 2020 at 15:48:49 UTC, sighoya wrote:
 I like the idea of an `implicitConversionOp` or 
 `implicitCoercionOp` more than multiple alias this since the 
 operator is separated from the source type.
User-defined implicit conversions have been proposed many, many times, and Walter has always rejected them. For example, here's a reply of his to a post from 2004:
 Implicit casting is a great idea. It's problems don't become 
 apparent for years, when battle-weary programmers eventually 
 conclude that it just causes more problems than it is worth. I 
 know that it is difficult to be convincing in a few lines about 
 this, but when the complexity of the classes goes beyond the 
 trivial, the interactions between them and other classes with 
 implicit casting becomes remarkably impenetrable.
https://forum.dlang.org/post/cqoj59$sle$1 digitaldaemon.com
Dec 26 2020
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Dec 26, 2020 at 04:26:14PM +0000, Paul Backus via Digitalmars-d wrote:
 On Saturday, 26 December 2020 at 15:48:49 UTC, sighoya wrote:
 I like the idea of an `implicitConversionOp` or `implicitCoercionOp`
 more than multiple alias this since the operator is separated from
 the source type.
User-defined implicit conversions have been proposed many, many times, and Walter has always rejected them. For example, here's a reply of his to a post from 2004:
 Implicit casting is a great idea. It's problems don't become
 apparent for years, when battle-weary programmers eventually
 conclude that it just causes more problems than it is worth. I know
 that it is difficult to be convincing in a few lines about this, but
 when the complexity of the classes goes beyond the trivial, the
 interactions between them and other classes with implicit casting
 becomes remarkably impenetrable.
https://forum.dlang.org/post/cqoj59$sle$1 digitaldaemon.com
I also used to be a fan of implicit conversions. Over time, though, I've come to agree with Walter. Implicit conversions are admittedly very convenient in the short term, but in the long term they tend to make code obtuse and hard to maintain. Over time I've come to regret deeply-ingrained implicit conversions I've done in my code with alias this. T -- People tell me I'm stubborn, but I refuse to accept it!
Dec 26 2020
parent reply sighoya <sighoya gmail.com> writes:
On Saturday, 26 December 2020 at 18:12:02 UTC, H. S. Teoh wrote:
Implicit conversions are admittedly very convenient in the short 
term, but in the long term they tend to make code obtuse and 
hard to maintain.
Could you elaborate a bit more? Did you have to many times pain with ambiguity errors or did your program run unexpectedly by resolving to the wrong method?
Dec 26 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, Dec 26, 2020 at 06:42:43PM +0000, sighoya via Digitalmars-d wrote:
 On Saturday, 26 December 2020 at 18:12:02 UTC, H. S. Teoh wrote:
 Implicit conversions are admittedly very convenient in the short
 term, but in the long term they tend to make code obtuse and hard to
 maintain.
Could you elaborate a bit more? Did you have to many times pain with ambiguity errors or did your program run unexpectedly by resolving to the wrong method?
It wasn't compile errors necessarily, but it was difficulty understanding what exactly the code is trying to do. And also painful when you thought one function was returning one type, but it actually returns a different type, so you can't pass it to the next function, but have to insert an extraneous conversion back to the original type. Or worse, you need to store a value in a struct somewhere, but due to implicit conversion the type you get out of a function does not match the type in the struct, and changing the struct's field type will lead to a huge amount of changes. There have also been occasions of actual bugs introduced by implicit conversions -- because some value implicitly converted earlier than expected, or got to the end via a different chain of conversions than you expected -- though this is relatively rare. Of course, you can always work around all of this somehow, perhaps by adding even more implicit conversions. Eventually, the code just accumulates all sorts of weird hacks and you're spending more time working around implicit conversions (or trying to understand them!) than actually making progress in the problem domain. It becomes a constant source of frustration and waste of time. Writing code without implicit conversions is tedious and annoying in the short term, but in the long term actually saves time by making the code clearer and more explicit, and more maintainable. T -- "I'm not childish; I'm just in touch with the child within!" - RL
Dec 26 2020
parent sighoya <sighoya gmail.com> writes:
Thanks a lot for your insights.

Some questions:

And also painful when you thought one function was returning one 
type,
 but it actually returns a different type,
You speak about the mix of templates and implicit conversion. I may be too limited to see that, but I thought once the template parameter is bound it can't change anymore, hence implicit conversion occurs without to rebind the template parameter. Am I wrong?
Or worse, you need to
 store a value in a struct somewhere, but due to implicit 
 conversion the type you get out of a function does not match 
 the type in the struct, and changing the struct's field type 
 will lead to a huge amount of changes
This could be true, but it relates to `alias this` which isn't either `implicitConversionOp` nor `implicitCoercionOp`.
There have also been
 occasions of actual bugs introduced by implicit conversions -- 
 because some value implicitly converted earlier than expected
Okay, maybe I need just a delightful example about this.
Dec 27 2020
prev sibling next sibling parent sighoya <sighoya gmail.com> writes:
On Saturday, 26 December 2020 at 16:26:14 UTC, Paul Backus wrote:
User-defined implicit conversions have been proposed many, many 
times, and Walter has always rejected them.
But have they ever considered adapting overload resolution?
Dec 26 2020
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
I'm speaking here from C++'s experience.

Implicit conversion operator overloading is in the category of ideas whose evil 
nature only becomes apparent after several years:

1. implicit declaration of variables

2. macros

3. operator overloading for non-arithmetic purposes

4. implicit conversion operator overloads

It's like burying your dead cat in Pet Sematary. Sure, it's cool when it comes 
back to life, but you'll be sssss-ooooo-rrrrr-eeeee !
Dec 27 2020
next sibling parent sighoya <sighoya gmail.com> writes:
On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:
 It's like burying your dead cat in Pet Sematary. Sure, it's 
 cool when it comes back to life, but you'll be 
 sssss-ooooo-rrrrr-eeeee !
Hmm, I wasn't aware that Walter is also a poet :).
 I'm speaking here from C++'s experience.
When talking about the merits of certain features and at the same time referring to their use in C++ inevitably biases the balance of pro and cons to the contra site. The point is, however, could we do it better than C++? Regarding templates, we already did.
 1. implicit declaration of variables
Did you the mention `auto` in conjunction with implicit conversion?
 2. macros
What has implicit conversion to do with macros, did you mean templates? As a counterargument, we already have classes and interfaces leading to the same characteristics regarding template overload resolution.
 3. operator overloading for non-arithmetic purposes
 4. implicit conversion operator overloads
Well I admit the evolving problem of ambiguity of implicit conversions in overload resolution. But what is harder for operator overloading than for normal method overloading? Overusing operators for nonsensical operations is already a code smell.
Dec 27 2020
prev sibling next sibling parent reply IGotD- <nise nise.com> writes:
On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:
 1. implicit declaration of variables
Can you give an example of an implicit declaration of a variable. Does C++ support this implicit declaration?
Dec 27 2020
parent Walter Bright <newshound2 digitalmars.com> writes:
On 12/27/2020 5:09 AM, IGotD- wrote:
 On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:
 1. implicit declaration of variables
Can you give an example of an implicit declaration of a variable.
int x1 = 0; xl = 3; // Oops!
 Does C++ support this implicit declaration?
No.
Dec 29 2020
prev sibling next sibling parent Q. Schroll <qs.il.paperinik gmail.com> writes:
On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:
 I'm speaking here from C++'s experience.
 [..]
 3. operator overloading for non-arithmetic purposes
I'd say, <, > and == aren't arithmetic operators, &, ^, and |, too, but one could disagree. Same for array dereferencing, indexing or getting an address. However, array concatenation with ~ for sure isn't arithmetic.
Dec 27 2020
prev sibling next sibling parent Max Samukha <maxsamukha gmail.com> writes:
On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:

 3. operator overloading for non-arithmetic purposes
I guess you intended to say it was a bad idea to redefine the well-established meaning of some operators defined by mathematics or the language itself (like '+' for concatenation or '<<' for IO)? Otherwise, operators are just functions with infix syntax and non-alpha-numeric names. I haven't heard any (reasonable) complaints about ">>=" or "<*>" in Haskell, for example.
Dec 27 2020
prev sibling parent 12345swordy <alexanderheistermann gmail.com> writes:
On Sunday, 27 December 2020 at 09:27:05 UTC, Walter Bright wrote:
 I'm speaking here from C++'s experience.
That's the thing isn't it? We don't have to do it the c++ way! Other languages done implicit conversions differently than c++, which requires further examination.
 Implicit conversion operator overloading is in the category of 
 ideas whose evil nature only becomes apparent after several 
 years:

 1. implicit declaration of variables
That's not a bug, but a good feature. Just have a "one and only one implicit conversion" for variables, then problem solved.
 2. macros
I think we agree that c macros is a bad idea. Templates on the other hand just needed type restrictions, to prevent nonsense if desired. Type functions are very promising on this.
 3. operator overloading for non-arithmetic purposes
Can this be said regarding arithmetic operator overloading in general?
 4. implicit conversion operator overloads
Which should have been opt-in not opt-out. The overload handing should be left up to the programmer not to the compiler.
Dec 27 2020
prev sibling next sibling parent sighoya <sighoya gmail.com> writes:
One point against `implicitConversionOp` is to which degree we 
work on copies after conversion.

What means actually conversion?
Did we create a whole new value not sharing any parts to its 
original value or is it more a mix of creation and sharing?
Example: create a new List and deep copy the elements out of the 
original list vs copy only the pointer of the elements out of the 
original list.

Because of this reason, I would favor for `implicitCoercionOp` 
and making `implicitConversionOp` explicit over `to!T` à la 
`into` in Rust.
Dec 27 2020
prev sibling parent reply Mike <slavo5150 yahoo.com> writes:
On Saturday, 26 December 2020 at 15:48:49 UTC, sighoya wrote:

 What is your opinion regarding this?
There have been a number of proposals that have attempted to address the niche that implicit conversion operators fill, including... 1. Implicit conversion operators 2. Implicit constructors 3. Multiple alias this As I recall, the only one that has not been outright rejected is multiple alias this (https://wiki.dlang.org/DIP66). In fact, it has been officially approved! But, the implementation (https://github.com/dlang/dmd/pull/8378) was never thoroughly reviewed let alone accepted, so it's unclear where things stand. Walter's primary objection, as I understood it, was the complexity it introduced for classes and its interplay with the inheritance hierarchy. Structs don't have an inheritance hierarchy, so I proposed a very simple solution: Multiple alias this for structs only. Classes already have what they need with D's kick-ass meta programming and multiple interface inheritance. It's only structs that really need such a feature. I wrote a slightly more detailed brain dump at https://forum.dlang.org/post/vggskphkqxtriqnavmnf forum.dlang.org, so I refer the reader there. Multiple alias this is already an approved DIP, so perhaps by reducing its scope to just structs, it may just need a champion willing to see an implementation through to completion. With multiple alias this for structs, implicit conversion may not be needed.
Dec 27 2020
parent reply sighoya <sighoya gmail.com> writes:
On Sunday, 27 December 2020 at 14:39:52 UTC, Mike wrote:
 There have been a number of proposals that have attempted to 
 address the niche that implicit conversion operators fill, 
 including...

 1.  Implicit conversion operators
It seems that DIP52(https://wiki.dlang.org/DIP52) wants to enable the complement behavior through `alias from` in addition to `alias to` which does reflect the `alias this` of today. `alias from` is akin to `alias this` coupled to its type. As I said, I don't appreciate this that much. Decoupling both source and target type from the implicit operator adds much more power and would subsume alias this. The point of decoupling is this: you can extend implicit conversions by importing `implicitConversionOps` from other modules s.t. method overloading of `implicitConversionOp` naturally extend the power of implicit conversions without to change the type signature of target or source type which is sadly the case with `alias this`. In the thread you linked here (https://forum.dlang.org/post/vggskphkqxtriqnavmnf forum.dlang.org), you even recommend deprecating alias this in favor of implicit operators. I like the idea, but deprecation isn't really that required, I think.
 2.  Implicit constructors
Was this DIP1004 (https://github.com/dlang/DIPs/blob/48f1e88f9740ec30558eff2fc7a18735ceb64352/DIPs/other/DIP1004.md)? It is interesting but doesn't directly relate to general implicit conversion as it is more focused on class constructors.
 3.  Multiple alias this
I don't appreciate it that much, because it isn't that extendable, i.e. enumerating all possible target types is impossible and adding them later might break your semver.
 As I recall, the only one that has not been outright rejected 
 is multiple alias this (https://wiki.dlang.org/DIP66).  In 
 fact, it has been officially approved!
Interesting, I wasn't aware of this.
 Walter's primary objection, as I understood it, was the 
 complexity it introduced for classes and its interplay with the 
 inheritance hierarchy.
Okay, true I must admit the overlap of structuralism with nominalism isn't easy, it isn't impossible to resolve the problem, it just needs to find a good convention, but it may end to more confusion than necessary. I can live with the restriction that classes are out of scope. Instead we could emphasize just to use `classObject.to` for explicit conversion.
  Structs don't have an inheritance hierarchy, so I proposed a 
 very simple solution:  Multiple alias this for structs only.
It kinda a solution, but what about interfaces. Nominal interface-relationships are too restrictive for me. Is it the same fuzz with interfaces as with classes? Or maybe we just should allow implicit conversion of classes and interfaces only if they don't inherit from any other class or interface excluding Object here. Also, I want pointers of structs to be implicit convertible to interfaces as otherwise we have a disparity between the concrete case where struct is passed by reference and wrapped into an interface and the generic case where struct does conform to one or more interfaces but are copied by value.
 Multiple alias this is already an approved DIP, so perhaps by 
 reducing its scope to just structs, it may just need a champion 
 willing to see an implementation through to completion.

 With multiple alias this for structs, implicit conversion may 
 not be needed.
It is implicit conversion, but a more restricted one leading to the creation of more types than necessary.
Dec 27 2020
parent Mike <slavo5150 yahoo.com> writes:
On Sunday, 27 December 2020 at 16:50:06 UTC, sighoya wrote:

 In the thread you linked here 
 (https://forum.dlang.org/post/vggskphkqxtriqnavmnf forum.dlang.org), you even
recommend deprecating alias this in favor of implicit operators. I like the
idea, but deprecation isn't really that required, I think.
I did not recommend it; I only mentioned it as an alternative. Indeed, deprecating `alias this` is not required; it was mentioned to emphasize that with the addition of the feature, the benefit `alias this` provides could be achieved in other ways.
 2.  Implicit constructors
Was this DIP1004 (https://github.com/dlang/DIPs/blob/48f1e88f9740ec30558eff2fc7a18735ceb64352/DIPs/other/DIP1004.md)?
No, I meant this C++ feature: https://en.cppreference.com/w/cpp/language/converting_constructor I suppose I may have used the wrong term.
 It is implicit conversion, but a more restricted one leading to 
 the creation of more types than necessary.
Only the types being converted from and converted to should be necessary.
Dec 27 2020