Why would you use an assignment in a condition?
Conditional StatementsLanguage AgnosticVariable AssignmentConditional Statements Problem Overview
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) {
...
}
Conditional Statements Solutions
Solution 1 - Conditional Statements
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();
}
Solution 2 - Conditional Statements
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.
The error checks could also be 'actions' — first_action()
, second_action()
, third_action()
— of course, rather than just checks. That is, they could be checked steps in the process that the function is managing. (Most often in the code I work with, the functions are along the lines of pre-condition checks, or memory allocations needed for the function to work, or along similar lines).
Solution 3 - Conditional Statements
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.
Solution 4 - Conditional Statements
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.
Solution 5 - Conditional Statements
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.
Solution 6 - Conditional Statements
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.
Solution 7 - Conditional Statements
The short answer is that Expression-oriented programming languages allow more succinct code. They don't force you to separate commands from queries.
Solution 8 - Conditional Statements
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);
}
Solution 9 - Conditional Statements
The other advantage comes during the usage of gdb. In the following code the error code is not known if we were to single step.
while (checkstatus() != -1) {
// process
}
Rather
while (true) {
int error = checkstatus();
if (error != -1)
// process
else
//fail
}
Now during single step we can know what was the return error code from the checkstatus().
Solution 10 - Conditional Statements
I find it very useful with functions returning optionals (boost::optional
or std::optional
in C++17):
std::optional<int> maybe_int(); // function maybe returns an int
if (auto i = maybe_int()) {
use_int(*i);
}
This reduces the scope of my variable, makes code more compact and does not hinder readability (I find).
Same with pointers:
int* ptr_int();
if (int* i = ptr_int()) {
use_int(*i);
}
Solution 11 - Conditional Statements
I used it today while programing in Arduino (C language).
Case
I have a transmitter and a receiver. The transmitter wants to send the data until it is received. I want to set a flag when the process is done.
while (!(newtork_joined = transmitter.send(data))) {
Serial.println("Not Joined");
}
Here:
- "transmitter.send" - returns true when the transmission is successful
- "newtork_joined " - is the flag I set when successful
Result
-
When the transmission is not successful, the flag is not set, while loop is true, it keeps executing
-
When successful, the flag is set, while loop is false, we exit
> Isn't beautiful?
Solution 12 - Conditional Statements
The reason is:
-
Performance improvement (sometimes)
-
Less code (always)
Take an example: There is a method someMethod()
and in an if
condition you want to check whether the return value of the method is null
. If not, you are going to use the return value again.
If(null != someMethod()){
String s = someMethod();
......
//Use s
}
It will hamper the performance since you are calling the same method twice. Instead use:
String s;
If(null != (s = someMethod())) {
......
//Use s
}