Previous Page
Next Page

5.5. Punctuation Variables

English for the less familiar punctuation variables.

Avoiding punctuation variables completely is, unfortunately, not a realistic option. For a few of the less commonly used variables, there is no good alternative. Or you may be maintaining code that is already structured around the extensive use of these variables, and reworking that code is impractical.

For example:

    local $| = 1;        # Autoflush output
    local $" = qq{\0};   # Hash subscript separator
    local $; =  q{, };   # List separator
    local $, =  q{, };   # Output field separator
    local $\ = qq{\n};   # Output record separator

    eval {
        open my $pipe, '<', '/cdrom/install |'
            or croak "open failed: $!";

        @external_results = <$pipe>;

        close $pipe
            or croak "close failed: $?, $!";
    };

    carp "Internal error: $@" if $@;

In such cases, the best practice is to use the "long" forms of the variables instead, as provided by use English. The English.pm module gives readable identifiers to most of the punctuation variables. With it, you could greatly improve the readability and robustness of the previous example:


    use English qw( -no_match_vars );   
# See the "Match Variables" guideline later
local $OUTPUT_AUTOFLUSH = 1; local $SUBSCRIPT_SEPARATOR = qq{\0}; local $LIST_SEPARATOR = q{, }; local $OUTPUT_FIELD_SEPARATOR = q{, }; local $OUTPUT_RECORD_SEPARATOR = qq{\n}; eval { open my $pipe, '/cdrom/install |' or croak "open failed: $OS_ERROR"; @extrenal_results = <$pipe>; close $pipe or croak "close failed: $CHILD_ERROR, $OS_ERROR"; }; carp "Internal error: $EVAL_ERROR" if $EVAL_ERROR;

The readability improvement is easy to see, but the greater robustness is perhaps less obvious. Take another look at the localization of the five variables:


    local $OUTPUT_AUTOFLUSH         = 1;
    local $SUBSCRIPT_SEPARATOR      = qq{\0};
    local $LIST_SEPARATOR           =  q{, };
    local $OUTPUT_FIELD_SEPARATOR   =  q{, };
    local $OUTPUT_RECORD_SEPARATOR  = qq{\n};

and compare it with the non-English version:

    local $| = 1;        # Autoflush output
    local $" = qq{\0};   # Hash subscript sep
    local $; =  q{, };   # List separator
    local $, =  q{, };   # Output field sep
    local $\ = qq{\n};   # Output record sep

Did you spot the mistake in the "punctuated" version? The comment on the second assignment claims that it is setting the hash subscript separator variable. But in fact the code is setting $", which is the list separator variable. Meanwhile, the third line's comment claims to be setting the list separator, whereas it's actually setting the hash-subscript separator variable: $;.

Somehow during development or maintenance those two variables were switched. Unfortunately, the values being assigned to them weren't swapped, nor were the comments. But, because these particular punctuation variables are relatively uncommon, it's easy to just trust the comments[*], which can blind you to the actual problem.

[*] Don't. Ever.

In comparison, the use English version doesn't even have comments. It doesn't need them. The long variable names document the purpose of each variable directly. And it's unlikely you'll mistakenly assign a value meant for the hash-subscript separator to the list separator instead. No matter how bad your spelling, the odds of accidentally typing $SUBSCRIPT_SEPARATOR when you meant to type $LIST_SEPARATOR are very slight.

There is one exception to this rule that all inescapable punctuation variables ought to be replaced with their use English synonyms. That exception is the $ARG variable:

    @danger_readings = grep { $ARG > $SAFETY_LIMIT } @reactor_readings;

Using $ARG is likely to make your code less clear to the average reader, compared with its original punctuation form:


    @danger_readings = grep { $_ > $SAFETY_LIMIT } @reactor_readings;

The general principle here is simple: If you had to look up a punctuation variable in the perlvar documentation when you were writing or maintaining the code, then most people will have to look it up when they read the code. And they'll probably have to look that variable up every single time they read the code.

So the first time you have to look up a punctuation variable in perlvar, replace it with the alternative construct suggested in Table 5-1, or else with its use English equivalent.

    Previous Page
    Next Page