www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Is opCast need, we have to!

reply Jesse Phillips <jessekphillips+D gmail.com> writes:
foobar Wrote:


   - converting to string can have formatting specified
   - converting string to numeric types with optional base parameter
   - converting integer to floating point specifies round/floor/ceiling/etc..

This was kind of my point, to! already specifies how to generically (an important part) to other types. And opCast overrides everything (which I don't wish to claim is incorrect, just asking).

I don't follow as to how this is important to have a generic interface. Can I specify parameters for conversion with to! as in my examples? I'd appreciate an example

Oops, sorry, though I don't see why it can't be specified in to!.
 2. const_cast: should be a _separate_ operator in order to prevent removing
const by mistake.
   const Base obj1 = new Derived();
   auto obj2 = cast(Derived)(obj1); // oops: meant to only down cast

I think to! should be changed such that this would be a ConvException.

This should not even compile. a run-time exception is better than current D but is still very weak.

See my bug report, http://d.puremagic.com/issues/show_bug.cgi?id=5307 After making it a runtime error, I made it just not compile. (Error message sucks though.)
 3. dynamic_cast: the language should provide a down cast operator for OO. 

Then the example above is invalid, though still valid when casting const double to int...

a down cast should _only_ perform dynamic down casts in the OO sense. so: Base foo = new Derived; Derived bar = downCast(foo); // compiles. performed at run-time [const] double -> int is not a down cast, it is a conversion.

I was referring to the need for const_cast
 Maybe std.math.floor should return an int, since they are implicitly converted
to real...
 
 and also:
 int x = ??; // some number
 double y = x; //compile-time error
 double z = double(x); // explicit

Other than overflow, which isn't fixed if made explicit, I don't see an issue with it being implicit.

besides the overflow issue you have mentioned, I also don't want special cases. No implicit conversions should be applied equally everywhere.

Then be explicit in all of _your_ code. That won't stop others from using implicit conversion, but you can just assume they are of the same type and be fine.
Dec 02 2010
next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
Jesse Phillips Wrote:

 besides the overflow issue you have mentioned, I also don't want special
cases. No implicit conversions should be applied equally everywhere. 

Then be explicit in all of _your_ code. That won't stop others from using implicit conversion, but you can just assume they are of the same type and be fine.

Now that I'm clearer on my own stance I should state my view on this. D has some unique rules for implicit conversion. You'll notice many of your complaints were _not_ valid in D. D allows for more implicit conversions then languages like C#, but not at the same cost as C (loss of data). For this reason I think experience from other languages can not dictate that implicit conversion is bad/unsafe in D. The desire to specify specific explicit conversions is understandable, as it prevents conversions that weren't expected. Cast should be avoided, D's implicit conversion rules help _prevent_ miss use of this drastically unsafe tool as you can just make assignments and issues are compiler errors which bring to your attention the problem. This is one of the reasons I want to restrict what to! allows for conversions. So we have: Safe conversions: implicit Type conversion: to!() Unsafe/forced/qualifier conversions: cast Even qualifier conversions have some library support to avoid using cast: std.exception.assumeUnique!() (maybe that should be in std.conv? Made sense in std.contract but not really exception).
Dec 02 2010
prev sibling parent reply foobar <foo bar.com> writes:
Jesse Phillips Wrote:

 foobar Wrote:
 
 
   - converting to string can have formatting specified
   - converting string to numeric types with optional base parameter
   - converting integer to floating point specifies round/floor/ceiling/etc..

This was kind of my point, to! already specifies how to generically (an important part) to other types. And opCast overrides everything (which I don't wish to claim is incorrect, just asking).

I don't follow as to how this is important to have a generic interface. Can I specify parameters for conversion with to! as in my examples? I'd appreciate an example

Oops, sorry, though I don't see why it can't be specified in to!.

how would the to! usage look like with these additions? I suspect at that stage the benefits of to! genericity will be lost. to!(int)("1010101", 2); / base 2 ? to!(int)(3.14, ..); // how do you specify a floor strategy here, enum? this quickly gets messy, ugly and redundant. int a = floor(3.14); // KISS - much better
 2. const_cast: should be a _separate_ operator in order to prevent removing
const by mistake.
   const Base obj1 = new Derived();
   auto obj2 = cast(Derived)(obj1); // oops: meant to only down cast

I think to! should be changed such that this would be a ConvException.

This should not even compile. a run-time exception is better than current D but is still very weak.

See my bug report, http://d.puremagic.com/issues/show_bug.cgi?id=5307 After making it a runtime error, I made it just not compile. (Error message sucks though.)

good :)
 
 3. dynamic_cast: the language should provide a down cast operator for OO. 

Then the example above is invalid, though still valid when casting const double to int...

a down cast should _only_ perform dynamic down casts in the OO sense. so: Base foo = new Derived; Derived bar = downCast(foo); // compiles. performed at run-time [const] double -> int is not a down cast, it is a conversion.

I was referring to the need for const_cast

Sorry, I lost you here. what are you talking about here?
  
 Maybe std.math.floor should return an int, since they are implicitly converted
to real...
 
 and also:
 int x = ??; // some number
 double y = x; //compile-time error
 double z = double(x); // explicit

Other than overflow, which isn't fixed if made explicit, I don't see an issue with it being implicit.

besides the overflow issue you have mentioned, I also don't want special cases. No implicit conversions should be applied equally everywhere.

Then be explicit in all of _your_ code. That won't stop others from using implicit conversion, but you can just assume they are of the same type and be fine.

since the entire point is to prevent bugs by having compiler checks, I don't see how the above conclusion helps me at all. I want the compiler to prevent me from getting the kinds of bugs previously shown.
Dec 02 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
foobar Wrote:

 how would the to! usage look like with these additions? I suspect at that
stage the benefits of to! genericity will be lost.
 
 to!(int)("1010101", 2); / base 2 ? 

to!(int)(base!(2)("1010101")); base!() returns a struct which can be created with strings/int/... and to! can change it to the different representations?
 to!(int)(3.14, ..); // how do you specify a floor strategy here, enum? 
 this quickly gets messy, ugly and redundant. 

to!(int)(floor(3.14));
 int a = floor(3.14); // KISS - much better

floor is not a type conversion! I could agree the type of floor should be an int, but it is not converting a real to an int. double a = cast(double) floor(3.14); Do you really want that?
 a down cast should _only_ perform dynamic down casts in the OO sense. so:
 Base foo = new Derived; 
 Derived bar = downCast(foo); // compiles. performed at run-time
 
 [const] double -> int is not a down cast, it is a conversion.

I was referring to the need for const_cast

Sorry, I lost you here. what are you talking about here?

Sorry, I am trying to shortcut on explanation. What I mean is, if you have a dynamic_cast operator you would not have the issue of casting away const when you meant to downcast. "const Base obj1 = new Derived(); auto obj2 = cast(Derived)(obj1); // oops: meant to only down cast" If you had dynamic cast, you won't use cast to change downcast. The implied question was, why do you need a const_cast then? But you are asking for only having const_cast and dynamic_cast, so it makes sense, oh and static_cast. To me, I don't see a need to distinguish between dynamic and static cast in D. These are not concepts you are going to confuse and in general don't even compile together: auto a = cast(double) b; If b is a class it won't compile (with the exception of opCast, which implies it is safe to cast to double anyway). But I think the implicit casting of D is important. It provides a way to do "safe" conversions allowing code to look cleaner. You shouldn't need to question if an assignment is performing a conversion that is causing an issue in your code, when using D. The type you are assigning too might be an issue, but this not a bug introduced by the conversion. For example you can assign a real to a float implicitly. This could result in a loss of precision. The bug did not come from an implicit conversion to float, it came because the precision of real was needed but float was used. My initial thought was it was a bad idea, but I came up with that reasoning to make myself feel good about D :D
 Then be explicit in all of _your_ code. That won't stop others from using
implicit conversion, but you can just assume they are of the same type and be
fine.
 

since the entire point is to prevent bugs by having compiler checks, I don't see how the above conclusion helps me at all. I want the compiler to prevent me from getting the kinds of bugs previously shown.

The compiler _is_ checking the code. There is nothing inherently wrong with converting an int to a double, except larger numbers can be held in an int (but making the conversion explicit will not resolve this, and won't result in people considering it). The example of: double d = 5 / 2; Is one place I agree could use an explicit conversion to double. I think this is the only major logic bug solved by forcing type conversions. But I also believe when the compiler complains the solution to fix it will be: double d = cast(double) 5 / 2; Even though it needs to wrap the five/two. That is because a complaining compiler does not make a thinking programmer, and the more it complains the less thinking. If you want say that the programmer sucks if they don't think about the changes they are making then, they also suck when they don't think 5 / 2 returns an int.
Dec 02 2010
next sibling parent Don <nospam nospam.com> writes:
Jesse Phillips wrote:
 foobar Wrote:
 
 how would the to! usage look like with these additions? I suspect at that
stage the benefits of to! genericity will be lost.

 to!(int)("1010101", 2); / base 2 ? 

to!(int)(base!(2)("1010101")); base!() returns a struct which can be created with strings/int/... and to! can change it to the different representations?
 to!(int)(3.14, ..); // how do you specify a floor strategy here, enum? 
 this quickly gets messy, ugly and redundant. 

to!(int)(floor(3.14));
 int a = floor(3.14); // KISS - much better

floor is not a type conversion! I could agree the type of floor should be an int, but it is not converting a real to an int. double a = cast(double) floor(3.14); Do you really want that?
 a down cast should _only_ perform dynamic down casts in the OO sense. so:
 Base foo = new Derived; 
 Derived bar = downCast(foo); // compiles. performed at run-time

 [const] double -> int is not a down cast, it is a conversion.



Sorry, I am trying to shortcut on explanation. What I mean is, if you have a dynamic_cast operator you would not have the issue of casting away const when you meant to downcast. "const Base obj1 = new Derived(); auto obj2 = cast(Derived)(obj1); // oops: meant to only down cast" If you had dynamic cast, you won't use cast to change downcast. The implied question was, why do you need a const_cast then? But you are asking for only having const_cast and dynamic_cast, so it makes sense, oh and static_cast. To me, I don't see a need to distinguish between dynamic and static cast in D. These are not concepts you are going to confuse and in general don't even compile together: auto a = cast(double) b; If b is a class it won't compile (with the exception of opCast, which implies it is safe to cast to double anyway). But I think the implicit casting of D is important. It provides a way to do "safe" conversions allowing code to look cleaner. You shouldn't need to question if an assignment is performing a conversion that is causing an issue in your code, when using D. The type you are assigning too might be an issue, but this not a bug introduced by the conversion. For example you can assign a real to a float implicitly. This could result in a loss of precision. The bug did not come from an implicit conversion to float, it came because the precision of real was needed but float was used. My initial thought was it was a bad idea, but I came up with that reasoning to make myself feel good about D :D
 Then be explicit in all of _your_ code. That won't stop others from using
implicit conversion, but you can just assume they are of the same type and be
fine.


The compiler _is_ checking the code. There is nothing inherently wrong with converting an int to a double, except larger numbers can be held in an int (but making the conversion explicit will not resolve this, and won't result in people considering it). The example of: double d = 5 / 2; Is one place I agree could use an explicit conversion to double. I think this is the only major logic bug solved by forcing type conversions. But I also believe when the compiler complains the solution to fix it will be: double d = cast(double) 5 / 2; Even though it needs to wrap the five/two. That is because a complaining compiler does not make a thinking programmer, and the more it complains the less thinking. If you want say that the programmer sucks if they don't think about the changes they are making then, they also suck when they don't think 5 / 2 returns an int.

I did a language proposal on this some time back, which was accepted, but which I haven't got around to making a patch for yet. The idea is that integer division (5 / 2) involves a discarding of the fractional part. The fact can be tracked as part of the integer range propagation (it is an int with a discarded fraction). An int with a discarded fraction cannot be implicitly converted to double. It can give a very informative error message too. That will catch this particular bug (which is a moderately common one).
Dec 02 2010
prev sibling parent reply foobar <foo bar.com> writes:
Jesse Phillips Wrote:

 foobar Wrote:
 
 how would the to! usage look like with these additions? I suspect at that
stage the benefits of to! genericity will be lost.
 
 to!(int)("1010101", 2); / base 2 ? 

to!(int)(base!(2)("1010101"));

semantically this is what i wanted but i still feel that a plain function would be easier on the eyes. for instance: int r = parseInt("101010", 2); // second parameter is optional and defaults to decimal base
 
 base!() returns a struct which can be created with strings/int/... and to! can
change it to the different representations?
 
 to!(int)(3.14, ..); // how do you specify a floor strategy here, enum? 
 this quickly gets messy, ugly and redundant. 

to!(int)(floor(3.14));
 int a = floor(3.14); // KISS - much better

floor is not a type conversion! I could agree the type of floor should be an int, but it is not converting a real to an int. double a = cast(double) floor(3.14);

you're right, point taken. to fix my previous example: int a = integer(floor(3.14)); // still simpler than the unified template syntax
 
 Do you really want that?
 
 a down cast should _only_ perform dynamic down casts in the OO sense. so:
 Base foo = new Derived; 
 Derived bar = downCast(foo); // compiles. performed at run-time
 
 [const] double -> int is not a down cast, it is a conversion.

I was referring to the need for const_cast

Sorry, I lost you here. what are you talking about here?

Sorry, I am trying to shortcut on explanation. What I mean is, if you have a dynamic_cast operator you would not have the issue of casting away const when you meant to downcast. "const Base obj1 = new Derived(); auto obj2 = cast(Derived)(obj1); // oops: meant to only down cast" If you had dynamic cast, you won't use cast to change downcast. The implied question was, why do you need a const_cast then? But you are asking for only having const_cast and dynamic_cast, so it makes sense, oh and static_cast.

Thanks for explaining. As you said, I want only const_cast and down_cast operators to be provided by the language.
 
 To me, I don't see a need to distinguish between dynamic and static cast in D.
These are not concepts you are going to confuse and in general don't even
compile together:
 
 auto a = cast(double) b;
 
 If b is a class it won't compile (with the exception of opCast, which implies
it is safe to cast to double anyway).

IMO, there is a need to distinguish the two because I may want to provide a conversion of my class type to a different class. contrived example: class Person {}; class Kid : Person {}; class Adult : Person {}; I want to be able to convert a Kid instance into an Adult instance when said kid turns 18.
 
 But I think the implicit casting of D is important. It provides a way to do
"safe" conversions allowing code to look cleaner. You shouldn't need to
question if an assignment is performing a conversion that is causing an issue
in your code, when using D.
 
 The type you are assigning too might be an issue, but this not a bug
introduced by the conversion. For example you can assign a real to a float
implicitly. This could result in a loss of precision. The bug did not come from
an implicit conversion to float, it came because the precision of real was
needed but float was used.
 
 My initial thought was it was a bad idea, but I came up with that reasoning to
make myself feel good about D :D
 

My opinion - this is a misfeature inherited from C. Assignment of incorrect type (e.g. a double value to an int) should be a compile-time error.
 Then be explicit in all of _your_ code. That won't stop others from using
implicit conversion, but you can just assume they are of the same type and be
fine.
 

since the entire point is to prevent bugs by having compiler checks, I don't see how the above conclusion helps me at all. I want the compiler to prevent me from getting the kinds of bugs previously shown.

The compiler _is_ checking the code. There is nothing inherently wrong with converting an int to a double, except larger numbers can be held in an int (but making the conversion explicit will not resolve this, and won't result in people considering it). The example of:

because of differences in representation this is also unsafe. Not all integral values can be represented accurately in a floating point type and this has nothing to do with size of int. I myself had such a bug where I expected a value of 2.0 as a result of some calculation but got 1.99998.. instead.
 
 double d = 5 / 2;
 
 Is one place I agree could use an explicit conversion to double. I think this
is the only major logic bug solved by forcing type conversions. But I also
believe when the compiler complains the solution to fix it will be:
 
 double d = cast(double) 5 / 2;
 
 Even though it needs to wrap the five/two. That is because a complaining
compiler does not make a thinking programmer, and the more it complains the
less thinking. If you want say that the programmer sucks if they don't think
about the changes they are making then, they also suck when they don't think 5
/ 2 returns an int.

i disagree with this logic. Take a look at ML family of languages to see that more checks do not make worse programmers.
Dec 02 2010
parent reply Jesse Phillips <jessekphillips+D gmail.com> writes:
foobar Wrote:

 Jesse Phillips Wrote:
 
 to!(int)(base!(2)("1010101"));

semantically this is what i wanted but i still feel that a plain function would be easier on the eyes. for instance: int r = parseInt("101010", 2); // second parameter is optional and defaults to decimal base

But then the logic for base conversion is spread out in: parseInt, parseDouble, toString, and what ever else a base conversion might be converted to/from. Though a helper function would be used by all. And how do you handle generic code? static if(is(T == int) parseInt... else static if(is(T == double)) parseDouble...
 you're right, point taken. to fix my previous example:
 int a = integer(floor(3.14)); // still simpler than the unified template syntax
 
 
 Do you really want that?


Yes, yes you do. Well you are in luck: int a = floor(3.14); // does not compile in D I think returning integer would be correct, but doesn't bother me to much? (Anyone else reading with an opinion?... numeric coders?)
 IMO, there is a need to distinguish the two because I may want to provide a
conversion of my class type to a different class.
 contrived example:
 class Person {};
 class Kid : Person {};
 class Adult : Person {}; 
 I want to be able to convert a Kid instance into an Adult instance when said
kid turns 18. 

Currently you can provide the conversion in the manner you desire Adult grownup = kid.canSmokeNow(); And by _not_ providing an opCast function, casting from Kid to adult will fail! to compile. Now of the cast types I do not know where this one falls, but dynamic cast is not it (I would think static cast).
 The type you are assigning too might be an issue, but this not a bug
introduced by the conversion. For example you can assign a real to a float
implicitly. This could result in a loss of precision. The bug did not come from
an implicit conversion to float, it came because the precision of real was
needed but float was used.
 
 My initial thought was it was a bad idea, but I came up with that reasoning to
make myself feel good about D :D
 

My opinion - this is a misfeature inherited from C. Assignment of incorrect type (e.g. a double value to an int) should be a compile-time error.

Could we please get one thing straight, D does not implicitly convert double/float/real to int. Or int to byte. You can select from these examples: int -> uint real -> double -> float int -> double... byte -> int and other similar combinations But stop using a completely invalid conversion example.
 The compiler _is_ checking the code. There is nothing inherently wrong with
converting an int to a double, except larger numbers can be held in an int (but
making the conversion explicit will not resolve this, and won't result in
people considering it). The example of:

because of differences in representation this is also unsafe. Not all integral values can be represented accurately in a floating point type and this has nothing to do with size of int. I myself had such a bug where I expected a value of 2.0 as a result of some calculation but got 1.99998.. instead.

I have never heard this. Not all values are representable in floating point, but I do not know of any issue representing integers. http://ideone.com/e8x5L If you received a value of 1.99998 from a calculation, it is an inherit issue with using double and not a conversion error from converting an int to a double.
 double d = 5 / 2;
 
 Is one place I agree could use an explicit conversion to double. I think this
is the only major logic bug solved by forcing type conversions. But I also
believe when the compiler complains the solution to fix it will be:
 
 double d = cast(double) 5 / 2;
 
 Even though it needs to wrap the five/two. That is because a complaining
compiler does not make a thinking programmer, and the more it complains the
less thinking. If you want say that the programmer sucks if they don't think
about the changes they are making then, they also suck when they don't think 5
/ 2 returns an int.

i disagree with this logic. Take a look at ML family of languages to see that more checks do not make worse programmers.

I said nothing about making the programmer worse due to checks, but do to excessive complaining. I do not think a programmer sucks for either mistake; I do think both are very easy mistakes to make. As Don pointed out there is a plan to fix this issue (not sure if it applies to when variables are used too). [OT] Why nagging people makes them numb. I believe you understand the premise of this. If something continually asks or tells you to do something, the answer becomes involuntary. Like dialogs that say do you wish to continue? Well I might not, but by the time I realize that I've already clicked yes (actually I might realize it 5 mins later and has nothing to do with being asked the question). But what I think you want is for the required action to be a safer action. For example, write now the solution is to insert a cast() which handles many different things and could perform one you weren't expecting. With many cast/conversion methods then you insert the appropriate method and it will complain that it can't do that. And now that I am seeing your view a little better I don't see this at play because: double d = double(5/2); would induce thinking, but so would: double d = cast(double)(5/2); (want an ! in there :P) I do not wish to argue against making things explicit, but I do want to figure out if there really is an issue in the way D does implicit conversions. So far I am seeing an opinion based on experience with C, but not D and an unwillingness to see that implicit conversion isn't harmful when done right.
Dec 02 2010
parent reply foobar <foo bar.com> writes:
Jesse Phillips Wrote:

 foobar Wrote:
 
 Jesse Phillips Wrote:
 
 to!(int)(base!(2)("1010101"));

semantically this is what i wanted but i still feel that a plain function would be easier on the eyes. for instance: int r = parseInt("101010", 2); // second parameter is optional and defaults to decimal base

But then the logic for base conversion is spread out in: parseInt, parseDouble, toString, and what ever else a base conversion might be converted to/from. Though a helper function would be used by all. And how do you handle generic code? static if(is(T == int) parseInt... else static if(is(T == double)) parseDouble...

I still haven't seen one example of generic code that uses a generic conversion. I remain unconvinced about this point and would appreciate an example. this is however a minor point in the discussion (stylistic issue) so let's move on to the more important parts.
 you're right, point taken. to fix my previous example:
 int a = integer(floor(3.14)); // still simpler than the unified template syntax
 
 
 Do you really want that?


Yes, yes you do. Well you are in luck: int a = floor(3.14); // does not compile in D I think returning integer would be correct, but doesn't bother me to much? (Anyone else reading with an opinion?... numeric coders?)
 IMO, there is a need to distinguish the two because I may want to provide a
conversion of my class type to a different class.
 contrived example:
 class Person {};
 class Kid : Person {};
 class Adult : Person {}; 
 I want to be able to convert a Kid instance into an Adult instance when said
kid turns 18. 

Currently you can provide the conversion in the manner you desire Adult grownup = kid.canSmokeNow(); And by _not_ providing an opCast function, casting from Kid to adult will fail! to compile. Now of the cast types I do not know where this one falls, but dynamic cast is not it (I would think static cast).

 The type you are assigning too might be an issue, but this not a bug
introduced by the conversion. For example you can assign a real to a float
implicitly. This could result in a loss of precision. The bug did not come from
an implicit conversion to float, it came because the precision of real was
needed but float was used.
 
 My initial thought was it was a bad idea, but I came up with that reasoning to
make myself feel good about D :D
 

My opinion - this is a misfeature inherited from C. Assignment of incorrect type (e.g. a double value to an int) should be a compile-time error.

Could we please get one thing straight, D does not implicitly convert double/float/real to int. Or int to byte. You can select from these examples: int -> uint real -> double -> float int -> double... byte -> int and other similar combinations But stop using a completely invalid conversion example.

uint foo = -1; // remember that this can be a result of a long calculation should the above compile in your opinion?
 The compiler _is_ checking the code. There is nothing inherently wrong with
converting an int to a double, except larger numbers can be held in an int (but
making the conversion explicit will not resolve this, and won't result in
people considering it). The example of:

because of differences in representation this is also unsafe. Not all integral values can be represented accurately in a floating point type and this has nothing to do with size of int. I myself had such a bug where I expected a value of 2.0 as a result of some calculation but got 1.99998.. instead.

I have never heard this. Not all values are representable in floating point, but I do not know of any issue representing integers. http://ideone.com/e8x5L

http://ideone.com/ksQDV
 If you received a value of 1.99998 from a calculation, it is an inherit issue
with using double and not a conversion error from converting an int to a double.
 
 double d = 5 / 2;
 
 Is one place I agree could use an explicit conversion to double. I think this
is the only major logic bug solved by forcing type conversions. But I also
believe when the compiler complains the solution to fix it will be:
 
 double d = cast(double) 5 / 2;
 
 Even though it needs to wrap the five/two. That is because a complaining
compiler does not make a thinking programmer, and the more it complains the
less thinking. If you want say that the programmer sucks if they don't think
about the changes they are making then, they also suck when they don't think 5
/ 2 returns an int.

i disagree with this logic. Take a look at ML family of languages to see that more checks do not make worse programmers.

I said nothing about making the programmer worse due to checks, but do to excessive complaining. I do not think a programmer sucks for either mistake; I do think both are very easy mistakes to make. As Don pointed out there is a plan to fix this issue (not sure if it applies to when variables are used too). [OT] Why nagging people makes them numb. I believe you understand the premise of this. If something continually asks or tells you to do something, the answer becomes involuntary. Like dialogs that say do you wish to continue? Well I might not, but by the time I realize that I've already clicked yes (actually I might realize it 5 mins later and has nothing to do with being asked the question). But what I think you want is for the required action to be a safer action. For example, write now the solution is to insert a cast() which handles many different things and could perform one you weren't expecting. With many cast/conversion methods then you insert the appropriate method and it will complain that it can't do that.

I understand what you mean about the confirmation dialog but as you said yourself above, I'm not asking for a confirmation dialog but rather using safer actions. I think we agree on this.
 And now that I am seeing your view a little better I don't see this at play
because:
 
 double d = double(5/2);
 
 would induce thinking, but so would:
 
 double d = cast(double)(5/2);
 
 (want an ! in there :P)

BUT, in the latter case cast(double) can do additional things that I don't need like remove constancy. cast() is problematic cause it overloads several semantics actions onto the same syntactic operator. It's also easier to read / understand code when you see "cast" and you know that it always means one specific operation (e.g. down cast). You don't need to read what's inside the cast to figure out if it removes constancy, does a static type conversion or perhaps a run-time down cast.
 
 I do not wish to argue against making things explicit, but I do want to figure
out if there really is an issue in the way D does implicit conversions. So far
I am seeing an opinion based on experience with C, but not D and an
unwillingness to see that implicit conversion isn't harmful when done right.

Dec 03 2010
next sibling parent Jesse Phillips <jessekphillips+D gmail.com> writes:
foobar Wrote:

 I still haven't seen one example of generic code that uses a generic
conversion. I remain unconvinced about this point and would appreciate an
example.
 this is however a minor point in the discussion (stylistic issue) so let's
move on to the more important parts.

Good point. I don't have one from experience. I can build on your example: class Elderly : Person { Elderly to(Person p) { Adult adult = to!Adult(p); return new Elderly(adult); } } The above would throw an exception if p was a Kid. Note that your solution does not provide compile time checking because you'd still need a dynamic cast to retrieve an Adult from your person. Providing a generic abstraction so when someone does find a use is a major style of Phobos.
 That was just one example. Let's discuss another one from your list then:
 uint foo = -1; // remember that this can be a result of a long calculation
 should the above compile in your opinion? 

No, I think int to uint should not be implicit. Maybe there is a reason other than C inheritance, I'm sure bearophile has a feature request for it.
 http://ideone.com/ksQDV 

I have an account so I get 15sec of runtime: http://ideone.com/9ZvNL Ok, I'm surprised this is successful. So I made another test that fails on my local machine, but strangely enough, succeeds on ideone... http://ideone.com/gOtYc Any way this demonstration is showing an issue with overflow. I have already stated that explicit casts do not solve this and got no disagreement from you.
 I understand what you mean about the confirmation dialog but as you said
yourself above, I'm not asking for a confirmation dialog but rather using safer
actions. 
 I think we agree on this. 

Yes, we do agree. What we don't agree on is the best way to make things safer. I am saying that implicit casts are not bad when data is not being lost. And to! is a good candidate for providing safe conversions (possible data lost but qualifiers remain). And that mixing conversions that loose data with ones that transform it (class conversion) is not an issue.
Dec 03 2010
prev sibling parent Adam Ruppe <destructionator gmail.com> writes:
foobar wrote:
 I still haven't seen one example of generic code that uses a generic
conversion.
 I remain unconvinced about this point and would appreciate an example.

Like half the generic code I've written does that. A direct example for this is my web.d - it makes automatic wrappers for D functions that are callable through a cgi interface. D: int myFunction(float a, string b) { .... } User's browser goes to: myprogram/my-function?a=1.5&b=something And sees the return value. The way the code works is: (pseudocode) foreach(member; thing.allMembers) { member.arguments args; foreach(i, arg; member.arguments) { args[i] = to!(typeof(arg))(cgi.get[arg.name]); } cgi.write(to!string(member(args))); } Everything in the web interface is string based on transport, so generic conversions are done to and from all the D types used. I did something similar with the command line version and with my D2 dmdscript port.
Dec 03 2010