Re: Add support implicit conversion between types
On 2013-09-07, 15:19, ilya-stromberg wrote: On Saturday, 7 September 2013 at 13:02:39 UTC, Simen Kjaeraas wrote: It's a bit weird in D though, as operators are instance methods, and opImplicitRightCast (or opImplicitCastFrom, which is the name used in discussions before, see WalterAndrei.pdf from back when dinosaurs roamed the earth) should definitely not be an instance method but a static one. That said, I belive opImplicitCastFrom is The Right Solution™. It's explicit, it's a bit ugly, but not so much it hurts. Yes, opImplicitCastFrom looks better. I didn't know about WalterAndrei.pdf file. Can you give me a link to the file? It's intresting to read. http://s3.amazonaws.com/dconf2007/WalterAndrei.pdf It's from the D conference back in 2007, as the URL indicates. opImplicitCastFrom is mentioned on page 22. It's kinda interesting to see what was happening back then and how things have progressed. -- Simen
Re: Add support implicit conversion between types
On 2013-09-06, 19:12, Dmitry Olshansky wrote: 06-Sep-2013 21:05, H. S. Teoh пишет: On Fri, Sep 06, 2013 at 05:14:48PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 14:26:17 UTC, H. S. Teoh wrote: I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? Yes, but it isn't always possible. It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support. Hmm, I see. This is an unfortunate limitation. In C++, writing int(123) actually works. Looks like D is lacking in this area. :-( I swear I've seen a pull request that enables it. This one? https://github.com/D-Programming-Language/dmd/pull/1356 It seems to be on its way. -- Simen
Re: Add support implicit conversion between types
On 2013-09-06, 15:57, ilya-stromberg wrote: On Friday, 6 September 2013 at 13:39:20 UTC, deadalnix wrote: You don't want a keyword for that. Something obscure and ugly is required. C# have operator overloading for this. We can use, for example, opImplicitRightCast struct Foo { Foo opImplicitRightCast(T)(T from); } It's a bit weird in D though, as operators are instance methods, and opImplicitRightCast (or opImplicitCastFrom, which is the name used in discussions before, see WalterAndrei.pdf from back when dinosaurs roamed the earth) should definitely not be an instance method but a static one. That said, I belive opImplicitCastFrom is The Right Solution™. It's explicit, it's a bit ugly, but not so much it hurts. -- Simen
Re: Add support implicit conversion between types
On Saturday, 7 September 2013 at 13:02:39 UTC, Simen Kjaeraas wrote: It's a bit weird in D though, as operators are instance methods, and opImplicitRightCast (or opImplicitCastFrom, which is the name used in discussions before, see WalterAndrei.pdf from back when dinosaurs roamed the earth) should definitely not be an instance method but a static one. That said, I belive opImplicitCastFrom is The Right Solution™. It's explicit, it's a bit ugly, but not so much it hurts. Yes, opImplicitCastFrom looks better. I didn't know about WalterAndrei.pdf file. Can you give me a link to the file? It's intresting to read. In C# this operator is static: class Foo { public Foo(int temp) { } public static implicit operator Foo(int temp) { return new Foo(temp); } } So, I agree, the opImplicitCastFrom should be also static.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:15:21 UTC, Benjamin Thaut wrote: Am 06.09.2013 15:01, schrieb Dicebot: Probably. But what is the gain? `foo(Foo(5))` looks better than `foo(5)` to me in every possible way. For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? Try implementing a custom string class in D that does not depend on the GC and you will know. Your code will be littered with explict constructions of strings, which makes it look totally ugly. Could you not just implement a .str property that does the conversion? Surely littering code with .str isn't too ugly? I understand the desire for it, but implicit coercions truly are evil.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 10:33:07 UTC, ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? I have some code like this: struct Foo { this(int i) { //do something useful } } void bar(Foo f) { //do something else } void main() { Foo f = 5;//works bar(f);//works bar(Foo(5));//works bar(5);//Error: function app.bar (Foo f) is not callable using argument types (int) } Actually D has this feature for classes: class A { this(int) {} } void foo(A a ...) {} void main() { foo(5); } This compiles and runs as expected. By the way, the code was fixed recently - before 2.063 this was allocating class on stack (so in D there were some kind of scoped stack classes), now this allocates on heap as usual. I don't see the rationale behind not working with structs.
Re: Add support implicit conversion between types
On Saturday, 7 September 2013 at 19:37:28 UTC, Maxim Fomin wrote: Actually D has this feature for classes: class A { this(int) {} } void foo(A a ...) {} void main() { foo(5); } This compiles and runs as expected. By the way, the code was fixed recently - before 2.063 this was allocating class on stack (so in D there were some kind of scoped stack classes), now this allocates on heap as usual. I don't see the rationale behind not working with structs. I don't see the rationale for it working for classes at all!
Re: Add support implicit conversion between types
I understand and support Kenjis request (linked in this thread) in the no casting, though version. And I find C++ or C# or Foo2k has this! a very troublesome approach and measure. Whatever feature is introducing inconsistencies is almost never worth it. We do have explicit conversion. If anyone feels that to look ugly he should ask what's worse, language inconsistencies or looks. A+ -R
Add support implicit conversion between types
Do you have any plans to support implicit conversion between types? I have some code like this: struct Foo { this(int i) { //do something useful } } void bar(Foo f) { //do something else } void main() { Foo f = 5;//works bar(f);//works bar(Foo(5));//works bar(5);//Error: function app.bar (Foo f) is not callable using argument types (int) } So, D can't use constructor to convert int to Foo implicitly. Can we add implicit keyword to allow do this: struct Foo { implicit this(int i) { //do something useful } } C++ allows this, but have explicit keyword. C# doesn't allow this, but have operator overloading for both implicit and explicit cases.
Re: Add support implicit conversion between types
Am 06.09.2013 12:33, schrieb ilya-stromberg: Do you have any plans to support implicit conversion between types? I have some code like this: struct Foo { this(int i) { //do something useful } } void bar(Foo f) { //do something else } void main() { Foo f = 5;//works bar(f);//works bar(Foo(5));//works bar(5);//Error: function app.bar (Foo f) is not callable using argument types (int) } So, D can't use constructor to convert int to Foo implicitly. Can we add implicit keyword to allow do this: struct Foo { implicit this(int i) { //do something useful } } C++ allows this, but have explicit keyword. C# doesn't allow this, but have operator overloading for both implicit and explicit cases. I also made almost the same suggestion some time ago. I would support a feature like this. -- Kind Regards Benjamin Thaut
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 10:33:07 UTC, ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 11:04:31 UTC, Peter Alexander wrote: Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade. Agreed. It was quite common source of troubles in my C++ days and have never offered much convenience.
Re: Add support implicit conversion between types
Am 06.09.2013 13:27, schrieb Dicebot: On Friday, 6 September 2013 at 11:04:31 UTC, Peter Alexander wrote: Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade. Agreed. It was quite common source of troubles in my C++ days and have never offered much convenience. Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 11:04:31 UTC, Peter Alexander wrote: On Friday, 6 September 2013 at 10:33:07 UTC, ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade. I think we should be able to do it, but in unconvenient ways. Like alias this + a property.
Re: Add support implicit conversion between types
Am 06.09.2013 13:44, schrieb deadalnix: On Friday, 6 September 2013 at 11:04:31 UTC, Peter Alexander wrote: On Friday, 6 September 2013 at 10:33:07 UTC, ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade. I think we should be able to do it, but in unconvenient ways. Like alias this + a property. But that doesn't work for construction. Also its not possible to do it for primitive types (especially string comes to mind)
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Am 06.09.2013 13:27, schrieb Dicebot: On Friday, 6 September 2013 at 11:04:31 UTC, Peter Alexander wrote: Implicit conversions open up a whole can of worms for the sake of a small amount of convenience. I'm not sure it's a fair trade. Agreed. It was quite common source of troubles in my C++ days and have never offered much convenience. Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. Totally agree. The default implicit conversion in C++ is a mistake. The conversion must be explicit by default (like in D now). The programmer should use implicit conversion ONLY IF IT SAFE (like ftom int to long). For any other cases programmer should use explicit conversion (default). Actually, this simple rule comes from C#: it have explicit conversions by default and ability to explicitly add implicit conversion. And I never had problems with it.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. It's not just that single arg constructors are by default implicit. Implicit conversions complicate things, like template argument deduction and overload resolution.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. Probably. But what is the gain? `foo(Foo(5))` looks better than `foo(5)` to me in every possible way. For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion?
Re: Add support implicit conversion between types
Am 06.09.2013 15:01, schrieb Dicebot: On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. Probably. But what is the gain? `foo(Foo(5))` looks better than `foo(5)` to me in every possible way. For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? Try implementing a custom string class in D that does not depend on the GC and you will know. Your code will be littered with explict constructions of strings, which makes it look totally ugly.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:01:14 UTC, Dicebot wrote: For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? For exaple, for generic code: T factorial(T)(T number) { return number = 1 ? 1 : number * factorial!T(number - 1); } void main() { //works: factorial!int(5); //doesn't work: factorial!BigInt(5); } It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) } }
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 10:33:07 UTC, ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? I have some code like this: struct Foo { this(int i) { //do something useful } } void bar(Foo f) { //do something else } void main() { Foo f = 5;//works bar(f);//works bar(Foo(5));//works I think that the good way, to do bar(5);//Error: function app.bar (Foo f) is not callable using argument types (int) } So, D can't use constructor to convert int to Foo implicitly. Can we add implicit keyword to allow do this: struct Foo { implicit this(int i) { //do something useful } } C++ allows this, but have explicit keyword. C# doesn't allow this, but have operator overloading for both implicit and explicit cases. It's difficult to never forget the explicit keyword in c++, and this little mistake can make you loose a lot of time. I prefer to only have explicit conversions with cast or constructors calls, that all make the code easier to understand.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:25:37 UTC, Flamaros wrote: It's difficult to never forget the explicit keyword in c++, and this little mistake can make you loose a lot of time. I prefer to only have explicit conversions with cast or constructors calls, that all make the code easier to understand. Yes. I sugest keep current D bechavior by default, but add implicit keyword. It allows to add implicit cast only if it SAFE.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:21:44 UTC, ilya-stromberg wrote: On Friday, 6 September 2013 at 13:01:14 UTC, Dicebot wrote: For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? For exaple, for generic code: ... So, what essentially is needed, is ability to implicitly convert literals of built-in types to user types, not any possible implicit conversion? I think allowing it with such restrictions can be reasonably clean.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:31:41 UTC, ilya-stromberg wrote: On Friday, 6 September 2013 at 13:25:37 UTC, Flamaros wrote: It's difficult to never forget the explicit keyword in c++, and this little mistake can make you loose a lot of time. I prefer to only have explicit conversions with cast or constructors calls, that all make the code easier to understand. Yes. I sugest keep current D bechavior by default, but add implicit keyword. It allows to add implicit cast only if it SAFE. You don't want a keyword for that. Something obscure and ugly is required.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:01:14 UTC, Dicebot wrote: On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. Probably. But what is the gain? `foo(Foo(5))` looks better than `foo(5)` to me in every possible way. This is very convenient when dealing with unknown types. Think JSON manipulation for instance.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:30:26 UTC, Dicebot wrote: So, what essentially is needed, is ability to implicitly convert literals of built-in types to user types, not any possible implicit conversion? I think allowing it with such restrictions can be reasonably clean. Yes, the ability to implicitly convert literals of built-in types to user types is REALLY needed. The 2-nd error from factorial example import std.bigint; void main() { assert(factorial!BigInt(BigInt(3)) == 6); //Error: incompatible types for ((1) : (number.opBinary(factorial(number.opBinary(1): 'int' and 'BigInt' } The correct factorial implementation is: T factorial(T)(T number) { enum T one = 1; return number = one ? one : number * factorial!T(number - one); } It's complicated, how do you think? not any possible implicit conversion? I didn't think about yet. May be you are right, but I think it can be also useful. For example, if you can't change user-defined type.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:39:20 UTC, deadalnix wrote: You don't want a keyword for that. Something obscure and ugly is required. C# have operator overloading for this. We can use, for example, opImplicitRightCast struct Foo { Foo opImplicitRightCast(T)(T from); }
Re: Add support implicit conversion between types
On Fri, Sep 06, 2013 at 03:21:42PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 13:01:14 UTC, Dicebot wrote: For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? For exaple, for generic code: T factorial(T)(T number) { return number = 1 ? 1 : number * factorial!T(number - 1); } void main() { //works: factorial!int(5); //doesn't work: factorial!BigInt(5); } I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? T -- Prosperity breeds contempt, and poverty breeds consent. -- Suck.com
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:50:25 UTC, ilya-stromberg wrote: On Friday, 6 September 2013 at 13:30:26 UTC, Dicebot wrote: So, what essentially is needed, is ability to implicitly convert literals of built-in types to user types, not any possible implicit conversion? I think allowing it with such restrictions can be reasonably clean. Yes, the ability to implicitly convert literals of built-in types to user types is REALLY needed. The 2-nd error from factorial example import std.bigint; void main() { assert(factorial!BigInt(BigInt(3)) == 6); //Error: incompatible types for ((1) : (number.opBinary(factorial(number.opBinary(1): 'int' and 'BigInt' } The correct factorial implementation is: T factorial(T)(T number) { enum T one = 1; return number = one ? one : number * factorial!T(number - one); } Or just: // import std.bigint; T factorial(T)(T number) { return number = 1 ? T(1) : number * factorial!T(number - 1); } // The problem though is that this requires uniform construction, which we don't have yet: http://d.puremagic.com/issues/show_bug.cgi?id=9112
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 14:26:17 UTC, H. S. Teoh wrote: I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? Yes, but it isn't always possible. It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 15:14:50 UTC, ilya-stromberg wrote: No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support. Yeah, this one, contrary, seems to be really crucial feature lacking.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 17:15:03 UTC, H. S. Teoh wrote: Hmm, could this be a possible (though somewhat ugly) workaround? foreach (T; IntegralTypeList) { assert(factorial(to!T(3) == 6)); } AFAIK, if T==int, then std.conv.to should simply alias itself away. And it *should* be able to handle ctors that take the requisite type, I think. I use: foreach (T; IntegralTypeList) { assert(factorial(cast(T)3) == 6)); } I works, but looks a little strange. I belive that compiler should optimise this (do nothing), but I am not sure.
Re: Add support implicit conversion between types
On Fri, Sep 06, 2013 at 10:05:47AM -0700, H. S. Teoh wrote: On Fri, Sep 06, 2013 at 05:14:48PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 14:26:17 UTC, H. S. Teoh wrote: I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? Yes, but it isn't always possible. It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support. Hmm, I see. This is an unfortunate limitation. In C++, writing int(123) actually works. Looks like D is lacking in this area. :-( [...] Hmm, could this be a possible (though somewhat ugly) workaround? foreach (T; IntegralTypeList) { assert(factorial(to!T(3) == 6)); } AFAIK, if T==int, then std.conv.to should simply alias itself away. And it *should* be able to handle ctors that take the requisite type, I think. T -- The number you have dialed is imaginary. Please rotate your phone 90 degrees and try again.
Re: Add support implicit conversion between types
On Fri, Sep 06, 2013 at 05:14:48PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 14:26:17 UTC, H. S. Teoh wrote: I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? Yes, but it isn't always possible. It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support. Hmm, I see. This is an unfortunate limitation. In C++, writing int(123) actually works. Looks like D is lacking in this area. :-( T -- Answer: Because it breaks the logical sequence of discussion. Question: Why is top posting bad?
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 15:47:27 UTC, Dicebot wrote: On Friday, 6 September 2013 at 15:14:50 UTC, ilya-stromberg wrote: As monarch_dodra pointed above, we haven't got uniform construction support. Yeah, this one, contrary, seems to be really crucial feature lacking. Yes, I agree. It solves problem of the difference between built-in and user-defined types for explicit cast.
Re: Add support implicit conversion between types
06-Sep-2013 21:05, H. S. Teoh пишет: On Fri, Sep 06, 2013 at 05:14:48PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 14:26:17 UTC, H. S. Teoh wrote: I thought the usual D idiom was to write factorial(5) and factorial(BigInt(5)) and let the compiler figure out which template instance you wanted? Yes, but it isn't always possible. It can be critical for more complex cases, when you call one generic function from another one, like this: unittest { alias TypeTuple!(byte, ubyte, short, ushort, int, uint, long, ulong, BigInt) IntegralTypeList; foreach(T; IntegralTypeList) { assert(factorial!T(3) == 6);//Error: factorial (BigInt number) is not callable using argument types (int) You could just write factorial(T(3)) ? No, I have the error: Error: function expected before (), not byte of type byte Error: function expected before (), not ubyte of type ubyte Error: function expected before (), not short of type short Error: function expected before (), not ushort of type ushort Error: function expected before (), not int of type int Error: function expected before (), not uint of type uint Error: function expected before (), not long of type long Error: function expected before (), not ulong of type ulong As monarch_dodra pointed above, we haven't got uniform construction support. Hmm, I see. This is an unfortunate limitation. In C++, writing int(123) actually works. Looks like D is lacking in this area. :-( I swear I've seen a pull request that enables it. -- Dmitry Olshansky
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 17:49:04 UTC, Jonathan M Davis wrote: Personally, I think that this is opening a whole can of worms that should never be opened. alias this already causes enough trouble for stuff like templates (primarily because it becomes far too easy to pass a template constraint and yet fail to work in the actual code). It's ultimately way cleaner and far less bug-prone to disallow this sort of implicit conversion, especially when so much D code is generic code. - Jonathan M Davis The problem with alias this is that it was designed to emulate inheritance, but was *diverted*, specifically, to emulate implicit casting instead. I think the results speak for themselves how well that worked... As a matter of fact, there are more than a few classes where I wish we could deprecate the static alias, and re-force explicit cast.
Re: Add support implicit conversion between types
On Friday, 6 September 2013 at 13:01:14 UTC, Dicebot wrote: On Friday, 6 September 2013 at 11:32:11 UTC, Benjamin Thaut wrote: Its only a source of troubles in C++ because it is the default behavior. But if you design a library it can make the usage of your api easier and also you have a few more options to stay backwards compatible with your old api. Probably. But what is the gain? `foo(Foo(5))` looks better than `foo(5)` to me in every possible way. For example, use case that justifies operator overloading (despite the danger) in my eyes is ability to replace built-in types with custom ones. What is the similar rationale for implicit conversion? In a few cases it's really useful. Assume that you have user-defined type, for example BigInt. You must implement A LOT OF foo functions which works only whith BigInt, like RSA, DSA and etc. For example, 100-500 different functions. Do you still want to write every time `foo(BigInt(5))`? (Remember: you have to use only BigInt). So, the short answer is the same as for operator overloading: in my eyes is ability to replace built-in types with custom ones. Yes, it can be dangerous, and we must to provide explicit cast by default. But in many cases it can simplify a life and a code.
Re: Add support implicit conversion between types
On Friday, September 06, 2013 12:33:05 ilya-stromberg wrote: Do you have any plans to support implicit conversion between types? I have some code like this: struct Foo { this(int i) { //do something useful } } void bar(Foo f) { //do something else } void main() { Foo f = 5;//works bar(f);//works bar(Foo(5));//works bar(5);//Error: function app.bar (Foo f) is not callable using argument types (int) } So, D can't use constructor to convert int to Foo implicitly. Can we add implicit keyword to allow do this: struct Foo { implicit this(int i) { //do something useful } } C++ allows this, but have explicit keyword. C# doesn't allow this, but have operator overloading for both implicit and explicit cases. Personally, I think that this is opening a whole can of worms that should never be opened. alias this already causes enough trouble for stuff like templates (primarily because it becomes far too easy to pass a template constraint and yet fail to work in the actual code). It's ultimately way cleaner and far less bug-prone to disallow this sort of implicit conversion, especially when so much D code is generic code. - Jonathan M Davis
Re: Add support implicit conversion between types
On Fri, Sep 06, 2013 at 07:25:21PM +0200, ilya-stromberg wrote: On Friday, 6 September 2013 at 17:15:03 UTC, H. S. Teoh wrote: Hmm, could this be a possible (though somewhat ugly) workaround? foreach (T; IntegralTypeList) { assert(factorial(to!T(3) == 6)); } AFAIK, if T==int, then std.conv.to should simply alias itself away. And it *should* be able to handle ctors that take the requisite type, I think. I use: foreach (T; IntegralTypeList) { assert(factorial(cast(T)3) == 6)); } I works, but looks a little strange. I belive that compiler should optimise this (do nothing), but I am not sure. I checked the disassembly for cast(T)5 for T==int and T==BigInt. Seems the compiler is doing the right thing in both cases. For T==int, the compiler just loads 5 directly into the register; for T==BigInt, it calls the BigInt ctor with 5 as parameter to construct an instance of BigInt. So, this seems to work, even though it looks ugly. T -- A linguistics professor was lecturing to his class one day. In English, he said, A double negative forms a positive. In some languages, though, such as Russian, a double negative is still a negative. However, there is no language wherein a double positive can form a negative. A voice from the back of the room piped up, Yeah, yeah.