www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - implicit conversion from bool to char, is it really necessary ?

reply deadalnix <deadalnix gmail.com> writes:
Today, I spent quite a lot of time because a stupid problem. It 
basically boil down to :

bool b; // Defined elsewhere.
string s = "somestring" ~ b?"":"somemorestring";

Obviously, I intended to write
string s = "somestring" ~ (b?"":"somemorestring");

but, due to operator priority, it is means
string s = ("somestring" ~ b)?"":"somemorestring";

So what ? So it compile without even a warning. I missed the error 
because I expected to get a type error in such case. So I assumed that 
the code was correct.

After checking in TDPL, it is stated that ubyte and char should 
implicitly cast to one another. And as bool implicitly convert to ubyte, 
this is effectively the specified behavior.

I think this is a rather problematic behavior. What is the point of have 
both byte and char types if both are implicitly convertible to one 
another (and have completely different semantic) ?
Sep 25 2012
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
deadalnix:

 bool b; // Defined elsewhere.
 string s = "somestring" ~ b?"":"somemorestring";

bool => char implicit conversion is not commonly useful in programs, but I think it's also not a common bug. On the other hand in past we have discussed a little about the bug-prone precedence of the ?: operator. Analysis of shared code repositories shows that this is a common source of bugs. So I think avoiding this bug has higher priority (and it's enough to avoid your specific bug). One of the ideas for D was that when the ?: is included in a larger expression, to requires parentheses around it. auto x1 = y1 ? z1 : w1; // OK auto x2 = x0 + (y1 ? z1 : w1); // OK auto x3 = (x0 + y1) ? z1 : w1); // OK auto x4 = x0 + y1 ? z1 : w1; // error auto x5 = y1 ? z1 : (y2 ? z2 : w2); // OK auto x6 = y1 ? z1 : y2 ? z2 : w2; // error In theory this increases the number of parentheses a little, but in practice in many similar situations I already put those parentheses, for readability and to avoid some of my mistakes. Bye, bearophile
Sep 25 2012
next sibling parent deadalnix <deadalnix gmail.com> writes:
Le 25/09/2012 21:24, bearophile a écrit :
 deadalnix:

 bool b; // Defined elsewhere.
 string s = "somestring" ~ b?"":"somemorestring";

bool => char implicit conversion is not commonly useful in programs, but I think it's also not a common bug.

Thi sis reversed logic. bool => char have know drawback. So it must bring something at least as important as the drawback (whatever how small it is) involved. I also wanted to discuss this subject specifically because it was a surprise to me and to other people on IRC. So I guess this feature is counter intuitive and contradict the rule that state that thing should work the way you expect them to work. I also already knew that ?: were sometime confusing. However, I skipped on that because I was sure (and wrong) that a type error would be triggered. It is a surprising behavior, so something you want to avoid as much as possible when creating a programing language.
 On the other hand in past we have discussed a little about the bug-prone
 precedence of the ?: operator. Analysis of shared code repositories
 shows that this is a common source of bugs. So I think avoiding this bug
 has higher priority (and it's enough to avoid your specific bug).

 One of the ideas for D was that when the ?: is included in a larger
 expression, to requires parentheses around it.

 auto x1 = y1 ? z1 : w1; // OK
 auto x2 = x0 + (y1 ? z1 : w1); // OK
 auto x3 = (x0 + y1) ? z1 : w1); // OK
 auto x4 = x0 + y1 ? z1 : w1; // error
 auto x5 = y1 ? z1 : (y2 ? z2 : w2); // OK
 auto x6 = y1 ? z1 : y2 ? z2 : w2; // error

 In theory this increases the number of parentheses a little, but in
 practice in many similar situations I already put those parentheses, for
 readability and to avoid some of my mistakes.

 Bye,
 bearophile

This would solve my particular bug, and I think it is a good thing to make this clearer.
Sep 25 2012
prev sibling parent deadalnix <deadalnix gmail.com> writes:
Le 26/09/2012 08:43, Brad Roberts a écrit :
 On 9/25/2012 12:24 PM, bearophile wrote:
 a common source of bugs. So...

Out of curiosity, what's your working definition of 'common' here? It seems to be something not far from "I've seen a report of it happening in more than one code base" which is overly broad, imho. I'm all for identifying classes of bugs and seeing what it might take to eliminate them, but there's a line where too much compiler 'help' is just annoying.

I do the mistake quite often myself. Usually fixed as fast as it is done because I know this is a tricky stuff. I guess bearophile noticed the same.
Sep 26 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 auto x3 = (x0 + y1) ? z1 : w1); // OK

Sorry, that was: auto x3 = (x0 + y1) ? z1 : w1; // OK Bye, bearophile
Sep 25 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
deadalnix:

 Thi sis reversed logic. bool => char have know drawback. So it 
 must bring something at least as important as the drawback 
 (whatever how small it is) involved.

I agree that implicit conversion from bool to char sounds useless or bad. But you already have a D2 language that few people use, so to break their code you need an important enough reason :-( Beside requiring the parentheses about the ?: operator when it's part of a larger expression, there are one or two other patterns that I'd like to see disallowed in D, like (!x & y). I think Walter agreed on disallowing it, but I have not heard about it since some time: http://d.puremagic.com/issues/show_bug.cgi?id=5409 Bye, bearophile
Sep 25 2012
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On 9/25/2012 12:24 PM, bearophile wrote:
 a common source of bugs. So...

Out of curiosity, what's your working definition of 'common' here? It seems to be something not far from "I've seen a report of it happening in more than one code base" which is overly broad, imho. I'm all for identifying classes of bugs and seeing what it might take to eliminate them, but there's a line where too much compiler 'help' is just annoying.
Sep 25 2012
prev sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Brad Roberts:

 Out of curiosity, what's your working definition of 'common' 
 here?  It seems to be something not far from "I've seen a
 report of it happening in more than one code base" which is 
 overly broad, imho.

Regarding (!x & y) I have seen studies (done by the Coccinelle devs) that shows how often this erroneous code pattern is present in the already reviewed Linux code. I have seen the same pattern in tens of articles from Viva64 where they apply their static verifier to large amounts (tens of millions, surely) lines of code, where they have spot tens of such bubs in already carefully debugged code. This pattern: int r = x op y ? : z : w; is present in several of those Viva64 reports. This is not a proof that such ?: requires parentheses (those reports just show common problems in already tested and widely used code, they don't suggest language improvements), but it's more than enough to open a discussion.
 but there's a line where too much compiler 'help' is just 
 annoying.

I agree, this requires judgement, and there's the risk of overdoing the compiler tests. As an example this thread and article discuss that the "unused imported modules are an error" and "unused variables is an error" rules of Go are too much harsh during code development: http://ridiculousfish.com/blog/posts/go_bloviations.html http://www.reddit.com/r/programming/comments/10fvmh/go_bloviations/ On the other hand I think the unused variables warning is useful, because they help keep code clean and avoid some bugs. Experience shows that in most programs the pattern (!x & y) is a bug, so I think disallowing it is an improvement for D, you will find it not easy to demonstrate the contrary. Bye, bearophile
Sep 26 2012