Question

I've been programming in C-derived languages for a couple of decades now. Somewhere along the line, I decided that I no longer wanted to write:

if (var)    // in C
if ($var)   # in Perl

when what I meant was:

if (var != 0)
if (defined $var and $var ne '')

I think part of it is that I have a strongly-typed brain and in my mind, "if" requires a boolean expression.

Or maybe it's because I use Perl so much and truth and falsehood in Perl is such a mine-field.

Or maybe it's just because these days, I'm mainly a Java programmer.

What are your preferences and why?

Was it helpful?

Solution

I like my ifs to make sense when read aloud:

if (is_it_happening) ...
if (number_of_sheep != 0) ...
if (pointer_to_something != NULL) ...

OTHER TIPS

I prefer

if (var != 0)

It's easier to read/understand. Since you write the code once but read quite a few times, easy reading is more important than easy writing.

It's quite simple. if( var ) tests for truthiness. if( var != 0 ) tests that it's not the number 0. THEY ARE NOT INTERCHANGABLE! There are three reasons.

First, using if( var != 0 ) to test for truth is more complicated. There's simply more there to read and understand. You have to grok that != and 0 is the idiom for "is true". Lacking a distinctive visual pattern, you have to do a little more studying to know that it's not the same as if( var == 0). This is a thin distinction, but worth mentioning. The fact that the if( 0 != var ) style exists gives credence. Better to just eliminate the problem and use if( var ) for truthiness.

Second, and more importantly, the intent must be clear. Are you testing for truth or are you testing for a number (or lack thereof)? if( var ) is testing for truth, if( var != 0 ) is testing a number. To determine anything else requires having knowledge of the author's style, which we must assume the maintenance programmer does not.

Third, there is an assumption here about the value of true and false and numeric operators which might work out in some languages and not in others. In Perl, and I think Javascript, too, empty string is false. A lot of operators return empty string for false. So testing truth with if( var != 0 ) leads to a warning. It becomes more stark when you do something more naive like if( var == 1 ) to mean truth, a clearly dangerous assumption. I have seem many junior programmers write that and in turn written functions that return odd, but true, numbers to punish this sort of thing. Or when I'm in a giving mood, I've sanitized my return value with return var ? 1 : 0.

In a related note, Perl will return the last evaluated expression from a subroutine, so it's not necessary to actually write return. Combine this with the idea people have that explicit return is slower and you get a lot of people abusing this fact.

sub set {
    my( $self, $key, $value ) = @_;

    $self->{$key} = $value;
}

set will return $value. Was that intended? I don't know. What I do know is someone will start relying on it. And the maintenance programmer won't know if they can change it. So I like to explicitly put a return in every non-trivial subroutine.

sub set {
    my( $self, $key, $value ) = @_;

    $self->{$key} = $value;
    return;
}

In that case I decided set will return nothing for the time being and that decision will be quite clear to both the reader and the user.

if (var)

Less to type, as long as you're sure you're not testing the wrong thing.

I prefer explicit tests unless the result inside the parentheses is a explicit boolean. The phrase "if (1)", while syntactically and semantically correct in terms of the language, is not logical. It should be true or false, not cast automatically.

I prefer readable logical code to less typing any day.

I also despise vehemently code of the form:

if (gotError == FALSE) ...
if (isComplete == TRUE) ...

If the boolean value is properly named (and it should be), the right way to do that is:

if (!gotError) ...
if (isComplete) ...

That's because (using reductio ad absurdum) boolVal == TRUE is simply another boolean value, so where do you stop?

if (isComplete == TRUE) ...
if ((isComplete == TRUE) == TRUE) ...
if (((isComplete == TRUE) == TRUE) == TRUE) ...
if ((((isComplete == TRUE) == TRUE) == TRUE) == TRUE)...

And so on, ad infinitum.

I would say that if you are comparing a true integer, then never do an implicit conversion to boolean, as it implies a different meaning to the variable.

But then again that style is so popular is probably isn't too big of a deal, but from my work with C#, I write my C++ code in this style:

Boolean or int that is basicaly a boolean:

if (val)

True integer with more than true/false being important:

if (val != 0)

Pointer of some kind:

if (val != NULL)

But as many people will say about coding styles that make no functional difference, it is probably best of all to be consistent, and if you are working with existing code, be consistent with that code.

In Perl if (defined $var and $var ne '') and if( $var) are NOT equivalent. Try it with $var=0. Conversely if you test on $var!=0 all strings that cannot be converted to numbers will fail the test (with a warning if you have them on).

So you must know exactly what your variable contains (number or string, whether it can be undef) so you can test accordingly.

I usually just write if( $var) and let Perl take care it. I believe that's easier to read, and that's the most common style in Perl.

Very often, actually, the proper test ends up being if( defined $var). That's where perl's new (in 5.10) // operator comes in handy. $var= $val // $default or often $var //= $default, where $var will receive $default only if $val (resp $var) is undef.

In Javascript (I don't know about other dynamic languages)

if (x) 

and

if (x != 0)

mean different things. I will use the former when the I expect x to hold a reference to an object or string that should not be zero length. Its a well known enough idiom.

If you have a value that is intended to be a boolean, you should feel comfortable just doing:

if ( var )
if ( $var )

If you have more specific requirements for your "boolean," you can always do some prep work/tests on your variable and assign it to another variable with better defined boolean values.

$shouldDoSomething = ( defined $var and $var ne '' ) ? 1 : 0;

if ( $shouldDoSomething ) {
    // Handle this case.
}

This can clean up the code quite a bit. It also helps if you intend to use this condition more than once. I find this happens pretty frequently, actually. Also, I feel like the above is far more readable than doing it inline:

if ( defined $var and $var ne '' ) {
    // Handle this case.
}

I go with readability like most people, I like being able to scan my code and read it without having to think too much, it goes hand in hand though with well named variable names. If your variable names make it sound like it should be a plain if(isPurchasable) then I go with it however it referes to a number or date or similar fasion I use if(stock > 0).

Having to write a comment for an if statement too me is a horrible idea if the expression is so simple, an if statement like below though I can see why comments should be used.

if(isPurchasable && stock > 0 && credit >= cost && !reserved) { 
     // Checks to see if customer can purchase product.
}

For numeric value scalars, I tend to write if ( $num_foo ) when $num_foo is in my control. If it’s user input or passed in from outside I either numify it first or spell out the test explicitly. It depends on a lot of factors. The main criterion is when and how it’s convenient to deal with undefined values, in order to avoid warnings.

To test for non-empty string, I used to write if ( $foo ) because the correct incantation is just way too much typing:

if ( defined $foo and length $foo )

But I wasn’t satisfied with this state of affairs so I instigated a change of behaviour for length undef in Perl 5.12, which throws a warning and returns 0 up to Perl 5.10 inclusive. In 5.12 it will just silently return undef. Therefore in non-boolean contexts you still get a warning, it just happens after the length call is evaluated rather than before. But in boolean contexts, there is no warning, so checking for a non-empty string is much easier to do correctly:

if ( length $foo )

I have a bunch ways of doing it:

for booleans:

if (x)

for ints:

if (x != 0)  // always compare, never assume true/false on int values

for pointers:

if (x /* != 0 */)  // I've always done this, not sure where I picked it up but I like it

These days, I think it's nicer to have a function call which describes what the logic actually means within the if statement

EDIT: Note, the 0 (intsead of NULL) is because I mainly use C++ these days

I'm surprised nobody's mentioned the other option, which the coding standards at a past employer of mine advocated:

if( 0 != x );

Where the constant was always listed first (especially more important with comparisons as they occasionally get typo'd to assignments - the source of many a bug)

It's the style I've used ever since in my C / Perl / C++ / VB.Net since (obviously the point becomes moot in C# whihc doesn't actually allow the if (x) scenario (unless x is actually a boolean, of course).

In C# it has been made explicitly illegal to write

if(x){}

unless x is a boolean type. There is no implicit conversion to bool from most other types.

I used this form a lot writing JavaScript, PHP and such to check for non null. But then again, I did get a few (easily detectable) bugs from it... I guess we are better off without it.

When using it on boolean variables, I strongly believe in easily readable names. I usually name boolean variables used like that with names beginning with "is", "has" or something similar.

I generally prefer if (var) or if ($var) if var is used as a boolean, even if there isn't any such type in the language.

I very much dislike constructs like if (!strcmp(...)) or if (var == true). The first tries to be too smart, the second too dumb -- although it scales well to if ((var == true) == true), ... ;-)

Some languages, like Perl and C++, provide extra or even user defined interpretations of trueness. If the conversion to a boolean seems too magic, remember it's basically just an is_true(var) or var.booleanValue(), or something like that behind the scene, just a more concise syntax.

Related to your question, I like to formulate conditions in a positive way. Instead of

if (!condition) {
    g();
}
else {
    f();
}

I prefer

if (condition) {
    f();
}
else {
    g();
}

Even if there is only a single branch, and the condition is not terribly simple. (An indication for that is the need for a comment.) For example, instead of

// explain reason for condition here
if (!condition) {
    f();
}

I prefer to phrase it as

if (condition) {
    // explain condition here
}
else {
    f();
}

To my way of thinking, simplicity is best.

The simpler you make the code, the better. Also, the less likely you'll make mistakes. Therefore, I would use

if(var)

But in the end, you should use what works best for your own way of thinking.

I don't always manage it, but I try to use

if (0 != var)

so it matches the defensive style

if (0 == var)

If you've got an int-bool in C that already holds a flag (and not a count), and you're testing it with "if (var != 0)", where does it end? Wouldn't "if ((var != 0) != 0)" be even better? :-)

I prefer a bare:

if ($canDo) {
}

instead of something like:

if ($canDo == true) {
}

Where a conditional is at all tricky, I comment it either explicitly with a comment, or implicitly with a good variable name. I also try to be very explicit when setting a boolean variable, preferring:

my($canDo) = !0;

to

my($canDo) = 1;

The latter is confusing; why assign a discrete value to a boolean?

Given Perl's many meanings to "evaluates to true", though, I can see why being more explicit is more practical in the long run. Still, one of the things I most like about Perl is its natural linguistic fluidity, and I prefer in my code to stick to that (leaving the comments and variable names to further clarify things, if needed).

VBScript? Well this bit of code declares a Variant, so bFlag is zero, which is effectively a False.

Dim bFlag
If bFlag Then

I don't like that. So even in VB, with the option of more specific declarations, I find myself being explicit no matter what the type.

Dim bFlag As Boolean
If bFlag = False Then

The other issue related to variable naming rules. If you're using an Hungarian-influenced regime, then you can tell visually that a given variable is boolean, so being specific about whether it's true or false is less of an issue. If, however, you're using some other variable naming technque, or worse, naming in an ad hoc way, then being specific about what's being tested for is appropriate.

Very often I use:

 if(x) {
       DoSomething;
       DoSomething2;
     }

Because this is less writing, and book which reading said:

Few good programmers use form if(x!=0), they use if(x).

But sometimes use and other form:

if(x!=0) 

HNY! :-)

I find that if(X) { /* ... */ } is much easier to read (in C, at least).

If i don't expect anyone else to read the code, I'd us the short one. If I expect someone to actually read my code, I would consider using the long form for readability.

I like Python constructions:

if var:
    return "I like the way I do it!"

It's just for example ;-)

There are languages in which you have no choice. In Specman, for instance, you can't write:

var x: uint;

if (x) {
    bla
};

But you can do:

var x: uint;

if (x != 0) {
    bla
};

or

var x: bool;

if (x) {
    bla
};

However, you can't do:

var x: bool;

if (x != 0) {
    bla
};

Because you can't compare a boolean to an integer.

Coming from C and Perl I always thought this to be annoying, until I actually started writing a lot in Specman. The code is simply clearer like this.

In my opinion, if (var != 0) is better.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top