Perl has a conditional operator that is the same a C's conditional operator.
To refresh, the conditional operator in C and in Perl is:
(test) ? (if test was true) : (if test was false)
and if used with an lvalue you can assign and test with one action:
my $x= $n==0 ? "n is 0" : "n is not 0";
I was reading Igor Ostrovsky's blog on A neat way to express multi-clause if statements in C-based languages and realized this is indeed a "neat way" in Perl as well.
For example: (edit: used Jonathan Leffler's more readable form...)
# ternary conditional form of if / elsif construct:
my $s=
$n == 0 ? "$n ain't squawt"
: $n == 1 ? "$n is not a lot"
: $n < 100 ? "$n is more than 1..."
: $n < 1000 ? "$n is in triple digits"
: "Wow! $n is thousands!" ; #default
Which reads a LOT easier than what many would write in Perl:
(edit: used cjm's more elegant my $t=do{ if };
form in rafi's answer)
# Perl form, not using Switch or given / when
my $t = do {
if ($n == 0) { "$n ain't squawt" }
elsif ($n == 1) { "$n is not a lot" }
elsif ($n < 100) { "$n is more than 1..." }
elsif ($n < 1000) { "$n is in triple digits" }
else { "Wow! $n is thousands!" }
};
Are there any gotchas or downside here? Why would I not write an extended conditional form in this manner rather than use if(something) { this } elsif(something) { that }
?
The conditional operator has right associativity and low precedence. So:
a ? b : c ? d : e ? f : g
is interpreted as:
a ? b : (c ? d : (e ? f : g))
I suppose you might need parenthesis if your tests used one of the few operator of lower precedence than ?:
. You could also put blocks in the form with braces I think.
I do know about the deprecated use Switch
or about Perl 5.10's given/when
constructs, and I am not looking for a suggestion to use those.
These are my questions:
Have you seen this syntax used in Perl?** I have not, and it is not in
perlop
orperlsyn
as an alternate to switch.Are there potential syntax problems or 'gotchas' with using a conditional / ternary operator in this way?
Opinion: Is it more readable / understandable to you? Is it consistent with Idiomatic Perl?
-------- Edit --
I accepted Jonathan Leffler's answer because he pointed me to Perl Best Practices. The relevant section is 6.17 on Tabular Ternaries. This allowed me to investigate the use further. (If you Google Perl Tabular Ternaries, you can see other comments.)
Conway's two examples are:
my $salute;
if ($name eq $EMPTY_STR) {
$salute = 'Dear Customer';
}
elsif ($name =~ m/\A ((?:Sir|Dame) \s+ \S+)/xms) {
$salute = "Dear $1";
}
elsif ($name =~ m/([^\n]*), \s+ Ph[.]?D \z/xms) {
$sa1ute = "Dear Dr $1";
}
else {
$salute = "Dear $name";
}
VS:
# Name format... # Salutation...
my $salute = $name eq $EMPTY_STR ? 'Dear Customer'
: $name =~ m/ \A((?:Sir|Dame) \s+ \S+) /xms ? "Dear $1"
: $name =~ m/ (.*), \s+ Ph[.]?D \z /xms ? "Dear Dr $1"
: "Dear $name"
;
My conclusions are:
Conway's
?:
example is more readable and simpler to me than theif/elsif
form, but I could see how the form could get hard to understand.If you have Perl 5.13.1, use
my $t=do { given { when } };
as an assignment as rafi has done. I thinkgiven/when
is the best idiom now, unless the tabular ternary format is better for your particular case.If you have Perl 5.10+ use
given/when
in general instead ofSwitch
or if you need some sort of case type switch.Older Perl's, this is a fine form for simple alternatives or as an alternate to a case statement. It is better than using
Switch
I think.The right to left associativity means the form is evaluated bottom to top. Remember that when using...