Perl的conditional运算符与C's conditional operator相同。
要刷新,C和Perl中的条件运算符是:
(test) ? (if test was true) : (if test was false)
如果与左值一起使用,您可以使用一个动作进行分配和测试:
my $x= $n==0 ? "n is 0" : "n is not 0";
我正在A neat way to express multi-clause if statements in C-based languages阅读Igor Ostrovsky的博客,并意识到这在Perl中确实是一种“整洁的方式”。
例如:(编辑:使用Jonathan Leffler更易读的形式......)
# 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
哪个读取比许多人在Perl中写的更容易:
(编辑:在rafi的回答中使用了cjm更优雅的my $t=do{ if };
形式)
# 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!" }
};
这里有任何问题或缺点吗?为什么我不以这种方式编写扩展条件形式而不是使用if(something) { this } elsif(something) { that }
?
条件运算符具有right associativity and low precedence。所以:
a ? b : c ? d : e ? f : g
被解释为:
a ? b : (c ? d : (e ? f : g))
如果您的测试使用的优先级低于?:
的少数运算符之一,我想您可能需要括号。你也可以把格子放在带支撑的形状中。
我确实知道已弃用的use Switch
或关于Perl 5.10的given/when
构造,我并不是在寻找使用它们的建议。
这是我的问题:
您是否看到过Perl中使用的这种语法?**我没有,而且它不在perlop
或perlsyn
作为切换的替代方法。
以这种方式使用条件/三元运算符是否存在潜在的语法问题或“陷阱”?
意见:你的可读性/可理解性更强吗?它与Idiomatic Perl一致吗?
--------编辑 -
我接受了Jonathan Leffler的回答,因为他指出我Perl Best Practices。 表格三元组的相关部分是6.17。这使我可以进一步调查使用情况。 (如果您使用Google Perl Tabular Ternaries,则可以看到其他评论。)
康威的两个例子是:
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"
;
我的结论是:
Conway的?:
示例比if/elsif
表单更易读,更简单,但我可以看到表单难以理解。
如果你有Perl 5.13.1,请使用my $t=do { given { when } };
作为rafi has done.的作业我认为given/when
现在是最好的习惯用法,除非表格三元格式更适合你的具体情况。
如果Perl 5.10+一般使用given/when
而不是Switch
,或者需要某种案例类型切换。
较旧的Perl,这是简单备选方案的良好形式,或作为案例陈述的替代。这比使用Switch
更好。
从右到左的关联性意味着从下到上评估表单。请记住,使用时......
答案 0 :(得分:19)
我在perl中看到过这个习惯用法。由于三元运算符? :
是一个运算符,它在perlop
中记录,而不是perlsyn
。
在我看来,它是一种惯用的Perl,但Perl的主要目的似乎是避免缺少正确的switch
语句,而不是写出巨大的if/else
- 级联。但是,这在几年前已经在perl 5.10.0中修复。这些天我没有看到很多理由不写这个,这似乎比(ab)使用三元组更具可读性:
given ($n) {
when (0) { $t = "$_ ain't squawt" }
when (1) { $t = "$_ is not a lot" }
when ($_ < 100) { $t = "$_ is more than 1..." }
when ($_ < 1000) { $t = "$_ is in triple digits" }
default { $t = "Wow! $_ is thousands!" }
}
或者,从perl 5.13.1开始,即使如此:
my $t = do {
given ($n) {
when (0) { "$_ ain't squawt" }
when (1) { "$_ is not a lot" }
when ($_ < 100) { "$_ is more than 1..." }
when ($_ < 1000) { "$_ is in triple digits" }
default { "Wow! $_ is thousands!" }
}
};
另一种选择是这样的,它适用于所有perl版本:
my @cases = (
[sub { $_ == 0 }, sub { "$_ ain't squawt" }],
[sub { $_ == 1 }, sub { "$_ is not a lot" }],
[sub { $_ < 100 }, sub { "$_ is more than 1..." }],
[sub { $_ < 1000 }, sub { "$_ is in triple digits" }],
[sub { 1 }, sub { "Wow! $_ is thousands!" }],
);
for my $case (@cases) {
local $_ = $n;
next unless $case->[0]->();
$t = $case->[1]->();
last;
}
虽然这避免了使用巨大的if/elsif/else
- 级联,并且不需要最近的perls的功能,但这个简单的例子可能不值得努力。但是,我可以非常看到这样的方法在很多条件下都有用,并且需要支持旧的perls。
(另请注意,您的初始示例不会处理$ n小于零或根本不是数字。)
来自cjm的注释:您也可以在所有版本的Perl 5中执行此操作:
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!" }
};
答案 1 :(得分:15)
条件运算符显示的布局很难阅读。 这更像是我记得Perl Best Practices推荐的内容:
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...
有时候使用带有if
表示法的更紧凑的表示法会更好:
if ($n == 0) { $t = "$n ain't squawt"; }
elsif ($n == 1) { $t = "$n is not a lot"; }
elsif ($n < 100) { $t = "$n is more than 1..."; }
elsif ($n < 1000) { $t = "$n is in triple digits"; }
else { $t = "Wow! $n is thousands!" ; }
这些重新格式化都强调了代码各个部分的相似性,使其更易于阅读和理解。
答案 2 :(得分:5)
我已经看过相当多的链条条件,有时会用它,并且总是讨厌它。这很方便但很难看,除非你走极端去格式化它并简化插页式广告。
一旦你遇到它们并且意识到这是一个成语,它们就不那么难以理解了。但是,更容易理解正确的switch语句。也有可能错误地放置冒号并以难以点的方式弄乱一切。
答案 3 :(得分:4)
还有另一种方式!
my $t = sub {
return "$n ain't squawt" if $n == 0;
return "$n is not a lot" if $n == 1;
return "$n is more than 1..." if $n < 100;
return "$n is in triple digits" if $n < 1000;
return "Wow! $n is thousands!";
}->();
我在几篇博文中谈到了这一点:
/ I3az /