www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Here's a sneaky little bug

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
import std.stdio;

void main()
{
    bool state = false;
    writeln("state is: " ~ state ? "true" : "false");
}

writes:
true

Whoa, what happened? Well, this should explain things:

    bool state = false;
    auto str = "bla" ~ state;

What (I assume) happens is the state boolean is converted to an int,
and since chars are ints in disguise and interchangeable you can
concatenate them with strings.

So the original code acted like it was written like this:
    bool state = false;
    writeln(("state is: " ~ state) ? "true" : "false");

And what we wanted was this:
    bool state = false;
    writeln("state is: " ~ (state ? "true" : "false"));

Anyway I just wanted to share how forgetting parens can introduce bugs in code.
Jun 24 2011
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 24 Jun 2011 14:28:45 -0400, Andrej Mitrovic  
<andrej.mitrovich gmail.com> wrote:

 import std.stdio;

 void main()
 {
     bool state = false;
     writeln("state is: " ~ state ? "true" : "false");
 }

 writes:
 true

 Whoa, what happened? Well, this should explain things:

     bool state = false;
     auto str = "bla" ~ state;

 What (I assume) happens is the state boolean is converted to an int,
 and since chars are ints in disguise and interchangeable you can
 concatenate them with strings.

 So the original code acted like it was written like this:
     bool state = false;
     writeln(("state is: " ~ state) ? "true" : "false");

 And what we wanted was this:
     bool state = false;
     writeln("state is: " ~ (state ? "true" : "false"));

 Anyway I just wanted to share how forgetting parens can introduce bugs  
 in code.

I can never remember precedence for ?:, so quite often I will over-parenthesize those expressions. I also typically over-parenthesize any expressions involving logical operations (i.e. & and |) Rule of thumb -- minimal parentheses that establish order of precedence, even if unnecessary, don't ever hurt :) But in any case, I'm really surprised "state is: " ~ false works at all... Since when can you append non-character types to strings? This is bound to result in bugs, since many people come from languages where appending a non-string type to a string results in a conversion to a string. I'd expect "state is: " ~ false to result in "state is: false" if it compiles at all. This may not be a bug, but it probably warrants an enhancement. D goes through great pains to avoid automatic string conversion, I think it should reject any attempts at it, even if they are accidental. -Steve
Jun 24 2011
prev sibling next sibling parent Ali =?iso-8859-1?q?=C7ehreli?= <acehreli yahoo.com> writes:
On Fri, 24 Jun 2011 14:49:24 -0400, Steven Schveighoffer wrote:

 On Fri, 24 Jun 2011 14:28:45 -0400, Andrej Mitrovic

     writeln("state is: " ~ state ? "true" : "false");


 I can never remember precedence for ?:, so quite often I will
 over-parenthesize those expressions.  I also typically over-parenthesize
 any expressions involving logical operations (i.e. & and |)

Yes!
 Rule of thumb -- minimal parentheses that establish order of precedence,
 even if unnecessary, don't ever hurt :)

And yes!
 I'd expect "state is: " ~ false to result in "state is: false"

bool is implicitly converted to char (as '\0' or '\1') and then the rest is all valid. Ali
Jun 24 2011
prev sibling next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.1195.1308940135.14074.digitalmars-d puremagic.com...
 import std.stdio;

 void main()
 {
    bool state = false;
    writeln("state is: " ~ state ? "true" : "false");
 }

 writes:
 true

 Whoa, what happened? Well, this should explain things:

    bool state = false;
    auto str = "bla" ~ state;

 What (I assume) happens is the state boolean is converted to an int,
 and since chars are ints in disguise and interchangeable you can
 concatenate them with strings.

 So the original code acted like it was written like this:
    bool state = false;
    writeln(("state is: " ~ state) ? "true" : "false");

 And what we wanted was this:
    bool state = false;
    writeln("state is: " ~ (state ? "true" : "false"));

 Anyway I just wanted to share how forgetting parens can introduce bugs in 
 code.

Yea, I've learned to always use parens around any ?: inside a larger expression (changing ?: without parens works fine, though). But that's a particularly bad scenario. Filed under "That damn implicit int->char conversion strikes again." Overly permissive implicit conversions are soooo C. Unfortunately, I don't think this general gotcha with ?: would be fixed with an order-of-operations change (it'd be nice if it could). Arithmetic and concat have higher precidence than comparison, so if we made ?: higher precidence than arithmetic/concat then we'd have to be very careful to do this: (a==b)?c:d every time we use a comparison for the ?:'s condition.
Jun 24 2011
parent "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:iu2njs$10d5$1 digitalmars.com...
 Yea, I've learned to always use parens around any ?: inside a larger 
 expression (changing ?: without parens works fine, though).

s/changing/chaining/
Jun 24 2011
prev sibling next sibling parent Kagamin <spam here.lot> writes:
Andrej Mitrovic Wrote:

 import std.stdio;
 
 void main()
 {
     bool state = false;
     writeln("state is: " ~ state ? "true" : "false");
 }

lol, if you don't know how an operator works, don't use in bigger expressions. You have local variables, right? It's also a bad practice to assemble messages from parts. Such code is non-localizable. writefln(gettext("state is: %s"), gettext(state ? "true" : "false")); vs writeln(gettext(state ? "state is: true" : "state is: false")); the former assumes english language word ordering. Concat also involves heap activity.
Jun 24 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/24/11, Kagamin <spam here.lot> wrote:
 lol, if you don't know how an operator works, don't use in bigger
 expressions.

It was a mistake while working on a different issue. I forgot to add the parens, and introduced a bug. People aren't robots and mistakes happen.
Jun 24 2011