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.