Usage of ‘if’ versus ‘unless’ for Perl conditionals

PerlIf StatementReadability

Perl Problem Overview


What are some guidelines for the best use of if versus unless in Perl code? Are there strong reasons to prefer one or the other in some situations?

Perl Solutions


Solution 1 - Perl

In Perl Best Practices, the advice is to never use unless. Personally, I think that's lunacy.

I use unless whenever there's a simple condition that I would otherwise write as if( ! ... ). I find the unless version to be more readable, especially when used as a postfix:

do_something() unless $should_not_do_that;

I recommend avoiding unless anytime things get more complicated, such as when you will have elsif or else blocks. (Fortunately, or perhaps unfortunately, depending on your perspective, there is no elsunless)

Also, any time a conditional is a complex expression made up of other booleans. For example,

unless( $foo and !$bar )

Is pretty damn confusing, and does not have any advantage over the equivalent if.

Solution 2 - Perl

Aside from one esoteric case1 unless is just syntactic sugar for if !. It exists to allow you to write code that is clearer and more expressive. It should be used when it achieves this goal and shunned when it impairs it.

I find unless to be most useful for flow control in loops. e.g.

while (<$fh>) {
    next unless /\S/;
    # ...
}

For simple negations I find it clearer than a negated if -- it's easy to miss that leading ! when reading code.

unless ($condition) {
    do_something();
}

if (!$condition) {
    do_something();
}

But don't write unless ... else, because that's just jarring.

In postfix form it provides a hint about what the expected path through the code is.

do_normal_thing() unless $some_unlikely_condition;


1) The last expression evaluated is different, which can affect the behavior of subs without an explicit return.

Solution 3 - Perl

A rule of thumb is that 'unless' should probably be used infrequently.

It is particularly useful in the postfix form, e.g.:

delete_old_widgets() unless $old_widget_count == 0

Situations where you should never use unless:

  • with a compound condition (and, or, not)
  • with an else clause

Solution 4 - Perl

I spent an hour recently trying to explain to someone how two nested 'unless' clauses worked, it was difficult to decypher without having to invert them into if statements with boolean logic.

If you try to convert it into English, it helps to guide you.

A simple unless works fine. For example.

'Unless you are quiet, I am going to ignore you'.

unless ($quiet) {
    ignore();
}

Although I think this works equally well

'If you are not quiet, I am going to ignore you'

if (not $quiet) {
    ignore();
}

when it starts getting complicated is when you have negation.

'Unless you are not noisy, I am going to ignore you'

unless ( ! $noisy) {
    ignore();
}

Far better written as

'If you are noisy, I am going to ignore you'

if ($noisy) {
    ignore();
}

So, don't use an 'unless' if you also have a negate.

Also don't use 'unless else'

unless ($quiet) {
    ignore();
}
else {
    give_a_sweet();
}

'Unless you are quiet, I will ignore you, otherwise I will give you a sweet'

Change it by inverting the condition.

if ($quiet) {
    give_a_sweet();
}
else {
    ignore();
}

'If you are quiet, I will give you a sweet, otherwise I will ignore you'.

with more than one condition, it get's messy.

unless ($quiet and not $fidgit) {
    punish();
}

'Unless you are quiet and you don't fidgit, I will punish you'.

(sorry my comprehension is failing here!)

again, negate it.

if (not $quiet or $fidgit) {
    punish();
}

'If you are not quiet, or you fidgit, I will punish you'.

the problem with using 'unless' even for the simplest cases, they often (by yourself or by outhe

I hope that makes it clear when you should, or should not, use unless?

(unless you don't have another opinion?)

Solution 5 - Perl

Though I understand the motivations for these sorts of questions I don't believe it's really sensible to boil down the use of something like unless into concrete rules of thumb. This, like a lot of auxiliary syntax in Perl is provided as a minor convenience for programmers to help them articulate themselves clearer at their own discretion; I've seen as much said in more ways than one by the lead developers throughout "Programming Perl". There's no higher purpose or rationalization. I'm well aware this finesses the question, but the only constraint I'd impose on using it is to see that it serves its broader purpose of making the code clearer. If it does, then all is well. Recognizing whether code is understandable is intuitive in itself and can't be reduced to a large handful of overly generalized usage conditions concerning every nuance of the built-in modifiers/operators/overall syntax, and where constraints and guidelines are needed in large group projects I don't think it would make sense to split hairs this finely.

Solution 6 - Perl

My opinion would be to never use unless. My reasons are:

  • I think the syntax makes code more difficult to read. Having a single method of doing an if makes thing simpler and more consistent.
  • If you need to add an else statement later on you should really change the unless to an if. It's just easier if it is already an if.
  • If the logic inside the unless statement becomes more complex then you can end up with odd code like "unless (x == 5 && y != 7). This is odd because there is a double negative on the second check.
  • There are other ways to negate things, ie x != 5
  • It's more consistent with other languages. I don't know of any other language that has an unless statement and I think there is a very good reason for this.

In perl there are really 4 ways to write an if statement, if, unless and then putting the check at the end of the line instead of the start. I much prefer a single consistent method that is consistent with other langauges also.

Just my $0.02 worth.

Solution 7 - Perl

Apropos...

> In Perl Best Practices, the advice is to never use unless. Personally, > I think that's lunacy.

After 20+ years preferring Perl over any of its alternatives (most of which would not exist had not Perl provided the template), I not only concur with the 'lunacy' verdict, I'm surprised (concerned) to hear that 'Best Practices' wants to get rid of it.

That said, I strongly prefer code written for clarity, as opposed to the implicitly obfuscated alternatives some Perl programmers adopt 'just because they can'. 'unless' is the unambiguous opposite of 'if', and therefore a very useful alternative to embedding a negation in an 'if' conditional, particularly if the conditional contains multiple operators. And that rationale applies even if followed by else/elsif.

Solution 8 - Perl

Just a personal opinion maybe, but I like to use Unless when the if condition would start with a !

Solution 9 - Perl

The syntax if(!$condition) is equivalent to unless($condition), and likewise if you swap the NOT'ing of the condition.

I personally prefer using only IF statements. Why? Because it's less to memorize. If you have 100 lines of code, half of it using unless() and the other half using if(), you'll need to spend more time debugging it than if it was just if() statements.

You may "get" the hang of unless and if, though, so that going between the two takes no time at all. But it's not just about if() versus unless(). Don't forget that...

if($condition) {
    #passed-condition code
} else {
    #failed-condition code
}

...is equivalent to...

unless(!$condition) {
    #passed-condition code
} else {
    #failed-condition code
}

But what about if(){...}elsif(){...}? How would you make an equivalent of that into unless(){...}elsunless(){...}? The more complicated the logic, the more difficult it becomes to go between if() and unless(). The less you have to remember and balance in your memory, the quicker you will be to debug your own code.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJSBձոգչView Question on Stackoverflow
Solution 1 - PerlfriedoView Answer on Stackoverflow
Solution 2 - PerlMichael CarmanView Answer on Stackoverflow
Solution 3 - PerlGrant McLeanView Answer on Stackoverflow
Solution 4 - Perluser3043717View Answer on Stackoverflow
Solution 5 - PerlcikkleView Answer on Stackoverflow
Solution 6 - PerlMikeKullsView Answer on Stackoverflow
Solution 7 - PerledwinView Answer on Stackoverflow
Solution 8 - PerlDavid BrunelleView Answer on Stackoverflow
Solution 9 - PerlHoldOffHungerView Answer on Stackoverflow