Документация
HTML CSS PHP PERL другое

Section 2.7.  Semicolons

 
Previous
Table of Contents
Next

2.7. Semicolons

Place a semicolon after every statement.

In Perl, semicolons are statement separators, not statement terminators, so a semicolon isn't required after the very last statement in a block. Put one in anyway, even if there's only one statement in the block:


    while (my $line = <>) {
        chomp $line;

        if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {
            push @comments, $2;
        }

        print $line;
    }

The extra effort to do this is negligible, and that final semicolon confers two very important advantages. It signals to the reader that the preceding statement is finished, and (perhaps more importantly) it signals to the compiler that the statement is finished. Telling the compiler is more important than telling the reader, because the reader can often work out what you really meant, whereas the compiler reads only what you actually wrote.

Leaving out the final semicolon usually works fine when the code is first written (i.e., when you're still paying proper attention to the entire piece of code):

    while (my $line = <>) {
        chomp $line;

        if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {
            push @comments, $2
        }

        print $line
    }

But, without the semicolons, there's nothing to prevent later additions to the code from causing subtle problems:

    while (my $line = <>) {
        chomp $line;

        if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {
            push @comments, $2
            /shift/mix
        }

        print $line
        $src_len += length;
    }

The problem is that those two additions don't actually add new statements; they just absorb the existing ones. So the previous code actually means:

    while (my $line = <>) {
        chomp $line;

        if ( $line =~ s{\A (\s*) -- (.*)}{$1#$2}xms ) {
            push @comments, $2 / shift() / mix( )
        }

        print $line ($src_len += length);
    }

This is a very common mistake, and an understandable one. When extending existing code, you will naturally focus on the new statements you're adding, on the assumption that the existing ones will continue to work correctly. But, without its terminating semicolon, an existing statement may be assimilated into the new one instead.

Note that this rule does not apply to the block of a map or grep if that block consists of only a single statement. In that case, it's better to omit the terminator:


    my @sqrt_results
        = map { sqrt $_ } @results;

because putting a semicolon in the block makes it much more difficult to detect where the full statement ends:

    my @sqrt_results
        = map { sqrt $_; } @results;

Note that this exception to the stated rule is not excessively error-prone, as having more than one statement in a map or grep is relatively unusual, and often a sign that a map or grep was not the right choice in the first place (see "Complex Mappings" in Chapter 6).

    Previous
    Table of Contents
    Next
    © 2000- NIV