September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to ilya-stromberg | 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 |
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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. |
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to ilya-stromberg | 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.
|
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to ilya-stromberg | 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? |
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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 |
September 06, 2013 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." |
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | 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.
|
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | 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.
|
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dicebot | 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.
|
September 06, 2013 Re: Add support implicit conversion between types | ||||
---|---|---|---|---|
| ||||
Posted in reply to ilya-stromberg | 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
|
Copyright © 1999-2021 by the D Language Foundation