Previous Page
Next Page

2.20. Ternaries

Format cascaded ternary operators in columns.

One operator that is particularly prone to creating long expressions is the ternary operator. Because the ? and : of a ternary have very low precedence, a straightforward interpretation of the expression-breaking rule doesn't work well in this particular case, since it produces something like:

    my $salute = $name eq $EMPTY_STR ? 'Customer'
                 : $name =~ m/\A((?:Sir|Dame) \s+ \S+)/xms ? $1
                 : $name =~ m/(.*), \s+ Ph[.]?D \z/xms ? "Dr $1" : $name;

which is almost unreadable.

The best way to lay out a series of ternary selections is in two columns, like so:

# When their name is...                    Address them as...
my $salute = $name eq $EMPTY_STR ? 'Customer' : $name =~ m/\A((?:Sir|Dame) \s+ \S+) /xms ? $1 : $name =~ m/(.*), \s+ Ph[.]?D \z /xms ? "Dr $1" : $name ;

In other words, break a series of ternary operators before every colon, aligning the colons with the operator preceding the first conditional. Doing so will cause the conditional tests to form a column. Then align the question marks of the ternaries so that the various possible results of the ternary also form a column. Finally, indent the last result (which has no preceding question mark) so that it too lines up in the results column.

This special layout converts the typical impenetrably obscure ternary sequence into a simple look-up table: for a given condition in column one, use the corresponding result from column two.

You can use the tabular layout even if you have only a single ternary:

    my $name = defined $customer{name} ? $customer{name}
             :                           'Sir or Madam'

Starting out this way makes it easier for maintainers to subsequently add new alternatives to the table. This idea is explored further in the "Tabular Ternaries" guideline in Chapter 6.

    Previous Page
    Next Page