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

Section 4.15.  Thin Commas

 
Previous
Table of Contents
Next

4.15. Thin Commas

Don't use commas to sequence statements.

Perl programmers from a C/C++ background are used to writing C-style for loops in Perl:

    # Binary chop search...
    SEARCH:
    for ($min=0,$max=$#samples, $found_target=0; $min<=$max; ) {
        $pos = int(($max+$min)/2);
        my $test_val = $samples[$pos];

        if ($target == $test_val) {
            $found_target = 1;
            last SEARCH;
        }
        elsif ($target < $test_val) {
            $max = $pos-1;
        }
        else {
            $min = $pos+1;
        }
    }

Each comma within the for initialization acts as a kind of "junior semicolon", separating substatements within the first compartment of the for.

After seeing commas used that way, people sometimes think that it's also possible to use "junior semicolons" within a list:

    print 'Sir ',
          (check_name($name), $name),
          ', KBE';

The intent seems to be to check the person's name just before it's printed, with check_name( ) tHRowing an exception if the name is wrong (see Chapter 13). The underlying assumption is that using a comma would mean that only the final value in the parentheses was passed on to print.

Unfortunately, that's not what happens. The comma actually has two distinct roles in Perl. In a scalar context, it is (as those former C programmers expect) a sequencing operator: "do this, then do that". But in a list context, such as the argument list of a print, the comma is a list separator, not technically an operator at all.

The subexpression (check_name($name), $name) is merely a sublist. And a list context automatically flattens any sublists into the main list. That means that the previous example is the same as:

    print 'Sir ',
          check_name($name),
          $name,
          ', KBE';

which will probably not produce the desired effect:

    Sir 1Tim Berners-Lee, KBE

The best way to avoid such problems is to adopt a style that limits commas to a single role: that of separating the items of lists. Then there can be no confusion between scalar comma operators and list comma separators.

If two or more statements need to be treated as a single statement, don't use scalar commas as "junior semicolons". Instead, use a do block and real semicolons:


    
# Binary chop search...
SEARCH: for (do{$min=0; $max=$#samples; $found_target=0;}; $min<=$max; ) {
# etc, as before
} print 'Sir ', do{ check_name($name); $name; }, ', KBE';

Or, better still, find a way to factor the sequence of statements out of the expression entirely:


    ($min, $max, $found_target) = (0, $#samples, 0);

    SEARCH:
    while ($min<=$max) {
        
# [Binary chop implementation as shown earlier]
} check_name($name); print "Sir $name, KBE";

    Previous
    Table of Contents
    Next
    © 2000- NIV