www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - DIP 52 - Implicit conversions

reply =?ISO-8859-1?Q?Simen_Kj=E6r=E5s?= <simen.kjaras gmail.com> writes:
http://wiki.dlang.org/DIP52

Abstract:
Implicit conversion to and from other types are useful, and is to some 
extent covered by existing language features. Some cases are currently 
not covered, but could be worthy additions to the toolbox.

I've tried to figure out good ways to add some sorely-needed implicit 
conversions to the language, but I'm sure there are details that need to 
be ironed out. In other words - destroy!

--
   Simen
Dec 11 2013
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Simen Kjærås:

 http://wiki.dlang.org/DIP52
 However, given that this code compiles and works perfectly:
 
 void baz() {
    import std.typecons;
    Tuple!(int, int) a;
    Tuple!(int, "x", int, "y") b;
    a = b; // Implicit conversion to less specialized type.
    b = a; // Implicit conversion to more specialized type.
I think "b = a;" is an accepts-invalid bug.
 void foo(TaggedUnion!(float, string, int, MyStruct) arg) {}
Do you mean Algebraic? Regarding the topic of implicit conversions, I propose to warn and then deprecate and then disallow the following two implicit casts, that only cause confusion, and are of no real utility: enum Foo { A, B } void main() { enum int i1 = 1; bool b1 = i1; // deprecate int i2 = Foo.A; // deprecate } Bye, bearophile
Dec 11 2013
next sibling parent =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On 2013-12-11 16:28, bearophile wrote:
 Simen Kjærås:

 http://wiki.dlang.org/DIP52
 However, given that this code compiles and works perfectly:

 void baz() {
    import std.typecons;
    Tuple!(int, int) a;
    Tuple!(int, "x", int, "y") b;
    a = b; // Implicit conversion to less specialized type.
    b = a; // Implicit conversion to more specialized type.
I think "b = a;" is an accepts-invalid bug.
I partly agree. I want this to compile: Tuple!(int, "x", int, "y") bar() { import std.typecons; Tuple!(int, int) a; return a; } And doing that without letting "b = a;" above compile seems counterintuitive and an unnecessary complexity.
 void foo(TaggedUnion!(float, string, int, MyStruct) arg) {}
Do you mean Algebraic?
Since a rewrite of Algebraic, supporting more features than the current version, is in progress, I chose to use a simple tagged union (which is what the current Algebraic is, I suppose).
 Regarding the topic of implicit conversions, I propose to warn and then
 deprecate and then disallow the following two implicit casts, that only
 cause confusion, and are of no real utility:

 enum Foo { A, B }
 void main() {
      enum int i1 = 1;
      bool b1 = i1; // deprecate
      int i2 = Foo.A; // deprecate
 }
I agree, but feel that this is orthogonal to the DIP. -- Simen
Dec 11 2013
prev sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Wednesday, 11 December 2013 at 15:28:51 UTC, bearophile wrote:
 Simen Kjærås:

 http://wiki.dlang.org/DIP52
 However, given that this code compiles and works perfectly:
 
 void baz() {
   import std.typecons;
   Tuple!(int, int) a;
   Tuple!(int, "x", int, "y") b;
   a = b; // Implicit conversion to less specialized type.
   b = a; // Implicit conversion to more specialized type.
I think "b = a;" is an accepts-invalid bug.
It's not. It works because of the user-defined Tuple.opAssign.
Dec 13 2013
prev sibling next sibling parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 11 December 2013 at 12:44:52 UTC, Simen Kjærås 
wrote:
 http://wiki.dlang.org/DIP52

 Abstract:
 Implicit conversion to and from other types are useful, and is 
 to some extent covered by existing language features. Some 
 cases are currently not covered, but could be worthy additions 
 to the toolbox.

 I've tried to figure out good ways to add some sorely-needed 
 implicit conversions to the language, but I'm sure there are 
 details that need to be ironed out. In other words - destroy!

 --
   Simen
In my opinion this DIP does not cover enough most important question for any DIP "what value does it bring that makes change worthy" or, in other words, "what problems is solves that can't be solved differently". Right now it is more like "this looks nice and you can do that" thing which does not sound convincing.
Dec 11 2013
prev sibling next sibling parent reply "deadalnix" <deadalnix gmail.com> writes:
On Wednesday, 11 December 2013 at 12:44:52 UTC, Simen Kjærås 
wrote:
 http://wiki.dlang.org/DIP52

 Abstract:
 Implicit conversion to and from other types are useful, and is 
 to some extent covered by existing language features. Some 
 cases are currently not covered, but could be worthy additions 
 to the toolbox.

 I've tried to figure out good ways to add some sorely-needed 
 implicit conversions to the language, but I'm sure there are 
 details that need to be ironed out. In other words - destroy!

 --
   Simen
Implicit conversion has proven to be a really bad idea in C++. What make your solution superior to existing ones ?
Dec 11 2013
next sibling parent reply =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On 2013-12-12 00:23, deadalnix wrote:
 On Wednesday, 11 December 2013 at 12:44:52 UTC, Simen Kjærås wrote:
 http://wiki.dlang.org/DIP52

 Abstract:
 Implicit conversion to and from other types are useful, and is to some
 extent covered by existing language features. Some cases are currently
 not covered, but could be worthy additions to the toolbox.

 I've tried to figure out good ways to add some sorely-needed implicit
 conversions to the language, but I'm sure there are details that need
 to be ironed out. In other words - destroy!

 --
   Simen
Implicit conversion has proven to be a really bad idea in C++. What make your solution superior to existing ones ?
C++ has shown that having implicit conversion *by default* is a really explicitly ask for it. If there's any critique of that anywhere (I expect there to be), I've been unable to find it. And of course it'll be possible to abuse implicit conversions, just like one can abuse function names - this is the old example of 'What does add(1,2) return? Why, "empty string", of course. After connecting to a database.'. There's a simple solution to that problem - fire the person who wrote that code, fix the code, and move on. Simply put, implicit conversions are not bad, nor good. They are exactly what you use them for. -- Simen
Dec 12 2013
parent reply "Meta" <jared771 gmail.com> writes:
On Thursday, 12 December 2013 at 09:15:56 UTC, Simen Kjærås wrote:
 C++ has shown that having implicit conversion *by default* is a 

 but you have explicitly ask for it. If there's any critique of 
 that anywhere (I expect there to be), I've been unable to find 
 it.
...Explicitly implicit conversions?
Dec 12 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Thursday, 12 December 2013 at 11:42:23 UTC, Meta wrote:
 On Thursday, 12 December 2013 at 09:15:56 UTC, Simen Kjærås 
 wrote:
 C++ has shown that having implicit conversion *by default* is 

 conversion, but you have explicitly ask for it. If there's any 
 critique of that anywhere (I expect there to be), I've been 
 unable to find it.
...Explicitly implicit conversions?
explicitly defined, implicitly applied.
Dec 12 2013
prev sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 12/12/13 10:15, Simen Kjærås wrote:
 Simply put, implicit conversions are not bad, nor good. They are exactly what
 you use them for.
Conversely, sometimes you want to be able to say, absolutely explicitly, "This function _must_ receive input of _this exact type_ with no implicit conversion allowed even if it normally would be." You and I both encountered that with Don's BigInt code, and I found his solution to be elegant but fragile (inasmuch as it's easy for a later maintainer to misunderstand why it's the way it is and wrongly "correct" it). So, you might want to factor that need also into your DIP.
Dec 12 2013
parent reply "IgorStepanov" <wazar mail.ru> writes:
On Thursday, 12 December 2013 at 14:47:17 UTC, Joseph Rushton 
Wakeling wrote:
 On 12/12/13 10:15, Simen Kjærås wrote:
 Simply put, implicit conversions are not bad, nor good. They 
 are exactly what
 you use them for.
Conversely, sometimes you want to be able to say, absolutely explicitly, "This function _must_ receive input of _this exact type_ with no implicit conversion allowed even if it normally would be."
You can write something like: void acceptMyType(T)(T arg) if(is(T == MyType)) { ... } Yes, this way is complex, but this situation is rare and we can put up with it. IMO, implicit conversion possibility for user types should be in a language, but this possibility should seems unattractive for user. User should know that he can use this ability only if he sure that he want it. May be opImplicitCastFrom method is a good solution, but it should be a static method whick accept T arg and returns UserType object. struct UserType { int a; static UserType opImplicitCastFrom(int a){return UserType(x);} } UserType o = 5; //should be converted to UserType o = UserType.opImplicitCastFrom(5); implicit calling of constructor should be deprecated in this case. UserType o2 = UserType (5); //use constructor void foo(UserType x); foo(5); // => foo(UserType.opImplicitCastFrom(5)); opImplicitCastFrom shouldn't be a non-static method (like opAssign), because we would need to call default constructor before opImplicitCastFrom call in this case, and if class doesn't define default constructor we wouldn't able to provide implicit conversion. Another suggestion: add special form of alias this construction: struct UserType { int a; alias myImplicitCast this; static UserType myImplicitCast(int a){return UserType(x);} } If alias this argument is a static function which accepts one parameter and returns typeof(this), it can be used for implicit conversion.
Dec 12 2013
next sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On 13/12/13 01:23, IgorStepanov wrote:
 You can write something like:

 void acceptMyType(T)(T arg) if(is(T == MyType))
 {
 ...
 }

 Yes, this way is complex, but this situation is rare and we can put up with it.
Yes, that's exactly the method I was thinking of. I really found it very beautiful when I saw it inside std.bigint and realized what it was meant to do, but I think it's _very_ prone to being accidentally "corrected" on the assumption that it's meant to be is(T : MyType).
Dec 13 2013
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Friday, 13 December 2013 at 10:39:41 UTC, Joseph Rushton 
Wakeling wrote:
 On 13/12/13 01:23, IgorStepanov wrote:
 You can write something like:

 void acceptMyType(T)(T arg) if(is(T == MyType))
 {
 ...
 }

 Yes, this way is complex, but this situation is rare and we 
 can put up with it.
Yes, that's exactly the method I was thinking of. I really found it very beautiful when I saw it inside std.bigint and realized what it was meant to do, but I think it's _very_ prone to being accidentally "corrected" on the assumption that it's meant to be is(T : MyType).
a quick "//no implicit conversion allowed" is surely adequate here. At the very least it would make someone think twice before breaking it.
Dec 13 2013
prev sibling parent =?UTF-8?B?U2ltZW4gS2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On 2013-12-13 01:23, IgorStepanov wrote:
 IMO, implicit conversion possibility for user types should be in a
 language, but this possibility should seems unattractive for user. User
 should know that he can use this ability only if he sure that he want it.
Absolutely.
 May be opImplicitCastFrom method is a good solution, but it should be a
 static method whick accept T arg and returns UserType object.
That was the plan. Updated the DIP to specify this. -- Simen
Dec 14 2013
prev sibling parent Max Klyga <email domain.com> writes:
On 2013-12-11 12:44:29 +0000, Simen Kjærås said:

 http://wiki.dlang.org/DIP52
 
 Abstract:
 Implicit conversion to and from other types are useful, and is to some 
 extent covered by existing language features. Some cases are currently 
 not covered, but could be worthy additions to the toolbox.
 
 I've tried to figure out good ways to add some sorely-needed implicit 
 conversions to the language, but I'm sure there are details that need 
 to be ironed out. In other words - destroy!
Although implicit conversions have some usecases, genrally they cause more damage then help. One could use suggested mechanism for defining covariance/contravariance for user types, but it would be too adhoc and fragile.
Dec 11 2013