Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

Comment on

( #3333=superdoc: print w/ replies, xml ) Need Help??
The if statement is known well to all but the most inexperienced Perl newbie. That's not pejorative: I was nearly that inexperienced myself when I wrote this, and did so as a means of self-education.

There's more to if statements than immediately meets the eye, though. They are control structures — ordered segments of algorithm — that can take several forms and be used in a number of different ways. They are, in short, boolean conditionals: either/or decisions leading to execution of further instructions.


if

The first thing the most basic if statement does is test for the truth of an expression. That expression is the "control statement" of the if statement. When the expression is evaluated as true, the code in the statement block is executed: when it is evaluated as false, the code in the statement block is ignored. Example:
if ($foo == 7) { $foo++; }

In the above example, the control statement expression is $foo == 7. If the contents of the scalar $foo are equal to 7, it evaluates as true, and the code within the statement block (delimited by the braces) is executed. If the contents of the scalar $foo are equal to some other number or string, or $foo is undefined, the code within that statement block is not executed. Thus:
#!/usr/bin/perl -w use strict; my $foo; $foo = 7; if ($foo == 7) { $foo++; } print($foo);

In the above example, executing the program simply causes the numeral 8 to be printed to STDOUT, which is normally the screen. (Typically you'd want to include a newline in what you print to STDOUT in a program like this, but it's not relevant to the example.) Meanwhile, in the following example, the STDOUT output is the numeral 6, because the increment operation $foo++ is not executed when the control statement is evaluated as false:
#!/usr/bin/perl -w use strict; my $foo; $foo = 6; if ($foo == 7) { $foo++; } print($foo);

That, of course, is all very basic. It gets slightly more interesting from here.


unless

The unless statement is a reversal of the control statement in an if statement. For instance, where above the control statement $foo == 7 causes the if statement block to be executed if evaluated as true, the code in the unless statement block is executed only if the control statement is evaluated as false. Thus, unless ($foo == 7) achieves exactly the same result as if ($foo != 7). The same is true, when working with strings, of the eq and ne operators.


if, reversed

Another way to represent an if statement is to use a one-line reversal of the normal order of it. Just as in English one can say both "If this happens, that follows," and "that follows if this happens," so too can you switch the order of expressions in an if statement. The above if statement that increments the value of $foo when the variable evaluates as true can be written as follows:
$foo++ if $foo == 7;

Clearly, using that reversed syntax can be an incredible saver of time and space when writing code. One must be aware of its rules and limitations, however. First of all, its elements are presented in an order opposite the usual method of representing the if conditional and statement block, and secondly you can (in general: there are ways around this) only execute one expression if the control statement evaluates as true. The longer form of the standard if statement allows for multiple instructions to be executed, while the shorter form only allows a single instruction to be executed.


unless, reversed

The same can be done with an unless statement as with an if statement. For instance, executing $foo++ in the event that $foo == 7 proves false would be represented by this unless statement:
$foo++ unless $foo == 7;


&&/|| == if/unless reversed

An even shorter, simpler way to represent both of the above control structures exists:
$foo++ if $foo == 7;
is the same as
$foo == 7 && $foo++;

and
$foo++ unless $foo == 7;
is the same as
$foo == 7 || $foo++;

The reason these last variants on the if and unless statements work requires some understanding of formal logical constructions beyond that of the more traditional forms of conditionals. The && operator works as an if conditional because of the manner in which it is applied by the interpreter:
  1. If $foo == 7 is true, then the value of the entire "and" expression is unknown. It cannot be evaluated as true or false as a whole until the part following the && operator is evaluated. The $foo++ portion is then executed and, because it's executed without fail, the complete expression $foo == 7 && $foo++; evaluates as true.

  2. If $foo == 7 is false, then the value of the second part of the entire statement ($foo++) is irrelevant because the whole statement can only be evaluated as true if both sides are true. The code for that expression stops before executing the increment operation.

Much the same occurs with the unless statement using the || operator. I leave the details of this as an exercise for the reader.


Appendix A: operator precedence

It's worth noting that operator precedence is important in using the && and || operators to create if and unless statements. In general, anything of higher precedence than the && or || operator in your statement is safe to use in your if statement or unless statement. If a lower-precedence operator is used, it can cause parts of your expressions that make up (for instance) the control statement to be attached to a new expression involving the && or || operator, rather than being used as you intended.

All standard arithmetic operators and comparison operators are of higher precedence than && and ||. Assignment operators are lower precedence. The and and or operators perform precisely the same functions as && and ||, respectively, but have a much lower precedence. This lower precedence causes them to be executed after even assignment operators, commas, and list operators.

Much of this confusion over precedence can be avoided, of course, by simply using parentheses liberally (and properly). There are two somewhat contradictory schools of thought regarding the use of parentheses to CYA when dealing with operator precedence: one is that you should use parentheses often and with enthusiasm to ensure proper code execution, and the other is that you should always ensure that you know the proper operator precedence and avoid parentheses where possible. On one hand, it's true that diligent writing of code with avoidance of parentheses makes for a cleaner program and is, perhaps, a sign of some competence. On the other hand, using parentheses even where they might sometimes be avoided can aid in ease of parsing code by eye and maintaining code later. Ultimately, decisions on the matter must be made by the programmer.


Appendix B: more actions in one-line if statements

As I said in if, reversed above, using one-line formats for the if and unless statement limits the programmer to only one executed statement when the control statement is evaluated as true (or, in the case of unless, evaluated as false). I also said there are ways around it, though. I'll use if, and not unless, for my examples.

For one thing, even the standard format for an if statement can be represented on one line. Thus, if ($foo == 7){$foo++;} does the same thing as the following:
if ($foo == 7) { $foo++; }

That's probably a bad idea, however. Using a statement block with braces around it allows for the flexibility of adding and subtracting statements within it, and collapsing it into one line renders the code less easy to read and maintain later without even making the code more succinct. The only keystrokes you really save involve your right pinky. The other methods of creating one-line if statements I mentioned above are recommended where they're appropriate.

Another means of expanding the functionality of the one-line if statement is to use the and statement as described in Appendix A above, which allows you to list multiple expressions for execution. For instance, you could do the following:
$foo == 7 and $foo++, $bar--;

You can also achieve much the same result through reliance on operator precendence. For instance, you could use this:
$foo == 7 && $foo++ && $bar++;

Other, innumerable exceptions apply to the one-line if statement's limitations — far more than I can get into in this brief treatment of the subject.


Thanks due the PerlMonks community members who contributed suggestions and comments in discussion below.


- apotheon
CopyWrite Chad Perrin

In reply to if variants by apotheon

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • Outside of code tags, you may need to use entities for some characters:
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Chatterbox?
    and the web crawler heard nothing...

    How do I use this? | Other CB clients
    Other Users?
    Others studying the Monastery: (6)
    As of 2014-11-23 02:11 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      My preferred Perl binaries come from:














      Results (127 votes), past polls