views:

803

answers:

8

In many languages assignments are legal in conditions. I never understood the reason behind this. Why would you write:

if (var1 = var2) {
  ...
}

instead of:

var1 = var2;
if (var1) {
  ...
}
+9  A: 

It can be useful if you're calling a function that returns either data to work on or a flag to indicate an error (or that you're done).

Something like:

while ((c = getchar()) != EOF) {
    // process the character
}

// end of file reached...

Personally it's an idiom I'm not hugely fond of, but sometimes the alternative is uglier.

Michael Burr
+11  A: 

It's more useful if you are calling a function:

if (n = foo())
{
    /* foo returned a non-zero value, do something with the return value */
} else {
    /* foo returned zero, do something else */
}

Sure, you can just put the n = foo(); on a separate statement then if (n), but I think the above is a fairly readable idiom.

Chris Young
+5  A: 

The idiom is more useful when you're writing a while loop instead of an if statement. For an if statement, you can break it up as you describe. But without this construct, you would either have to repeat yourself:

c = getchar();
while (c != EOF) {
    // ...
    c = getchar();
}

or use a loop-and-a-half structure:

while (true) {
    c = getchar();
    if (c == EOF) break;
    // ...
}

I would usually prefer the loop-and-a-half form.

Greg Hewgill
+4  A: 

GCC can help you detect (with -Wall) if you unintentionally try to use an assignment as a truth value, in case it recommends you write

if ((n = foo())) {
   ...
}

I.e. use extra parenthesis to indicate that this is really what you want.

JesperE
+18  A: 

It's more useful for loops than if statements.

while( var = GetNext() )
{
  ...do something with var 
}

Which would otherwise have to be written

var = GetNext();
while( var )
{
 ...do something
 var = GetNext();
}
Gerald
I agree - but would write: while ((var = GetNext()) != 0) { ... } without thinking twice, partly because GCC complains if I don't with my default compilation options.
Jonathan Leffler
+1  A: 

In PHP, for example, it's useful for looping through SQL database results:

while ($row = mysql_fetch_assoc($result)) {
    // Display row
}

This looks much better than:

$row = mysql_fetch_assoc($result);
while ($row) {
    // Display row
    $row = mysql_fetch_assoc($result);
}
yjerem
This also has the neat side-effect of $row not living beyond that loop and therefore being eligible for garbage collection sooner (in languages that do GC anyway).
Darren Greaves
+2  A: 

I find it most useful in chains of actions which often involve error detection, etc.

if ((rc = first_check(arg1, arg2)) != 0)
{
    report error based on rc
}
else if ((rc = second_check(arg2, arg3)) != 0)
{
    report error based on new rc
}
else if ((rc = third_check(arg3, arg4)) != 0)
{
    report error based on new rc
}
else
{
    do what you really wanted to do
}

The alternative (not using the assignment in the condition) is:

rc = first_check(arg1, arg2);
if (rc != 0)
{
    report error based on rc
}
else
{
    rc = second_check(arg2, arg3);
    if (rc != 0)
    {
        report error based on new rc
    }
    else
    {
        rc = third_check(arg3, arg4);
        if (rc != 0)
        {
            report error based on new rc
        }
        else
        {
            do what you really wanted to do
        }
    }
}

With protracted error checking, the alternative can run off the RHS of the page whereas the assignment-in-conditional version does not do that.

Jonathan Leffler
+1  A: 

The short answer is that Expression-oriented programming languages allow more succinct code. The don't force you to separate commands from queries.

Hugh Allen