![](/img/trans.png)
[英]Ternary expression containing loose comparison in else branch yields unexpected result
[英]Ternary operator in perl yields unexpected result when assigning a variable in the statement
我正在尝试从 php 过渡到 perl 并且预计会遇到一些怪异。 我不明白为什么我的代码的一个版本与另一个版本相比有效。
这失败了:
sub tester
{
$return;
($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old person";
return $return;
}
print "how old are you?";
$a = <>;
chomp $a;
print tester($a); #both result in "youre an old person"
但是这个有效:
sub tester
{
return ($_[0] < 10) ? "youre a youngin" : "youre an old person";
}
print "how old are you?";
$a = <>;
chomp $a;
print tester($a);
这里的真正区别是什么?!
它与 Perl 的运算符优先级有关。 在 Perl 中,
($_[0] < 10) ? $return = "youre a youngin" : $return = "youre an old fart";
和
( ($_[0] < 10) ? $return = "youre a youngin" : $return ) = "youre an old fart";
注意paren绑定到FRONT。
这导致 Perl 的另一个令人困惑的功能:条件左值:您可以这样做(CONDITION? $ASSIGN_A_IF_CONDITION_IS_TRUE: $ASSIGN_B_IF_CONDITION_IS_FALSE) = 2
这是一个修复
($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");
编辑:
然而,大多数人会写
$return = ($_[0] < 10) ? "youre a youngin" : "youre an old fart";
,节省了两次键入变量的冗余。
根据Perl和Z2FEC392304A5C23AC138DA222847F9B7CZ DOCS ?:
Z0114AD0114AD0111D7282728F1836FE12FE12522323232323232323232312574EFY44Z ?:
(http://perldoc.perl.org/perlop.html) (http://php.net/manual/en/language.operators.precedence.ZE1BFD762321E409CEE4AC0B6E841963C)
啊,你已经发现了为什么?:
是一个坏主意,除了在微不足道的情况下。
运算符优先级是问题所在。 你很可能想要这样做:
$return = ($_[0] < 10) ? "you're a youngin'" : "you're an old fart";
不过,您的代码还有一些其他问题。
my
运算符明确执行此操作。use strict
和use warnings
。 这些编译指示禁用了古老的 Perl 恶作剧,并警告可能是错误的可疑操作。@_
; 没有什么理由直接在 function 中使用$_[0]
。 (这样做很危险,因为@_
是别名;您可以更改调用者的变量!)所以你可能想要更像这样的东西:
use strict;
use warnings;
sub tester {
my ($age) = @_;
if ($age < 10) {
return "you're a youngin'";
}
else {
return "you're an old fart";
}
}
print "how old are you? ";
my $age = <>;
chomp $age;
print tester($age);
请注意, my $x =...
声明了一个变量并分配了一个值,而my ($x, $y, $z) =...
声明了多个变量并将一个列表解压缩到其中。
my
变量称为词法变量,仅存在于您声明它们的块中; 它们不像 PHP 变量那样是函数范围的。 实际上,您可能应该只在perlsub中阅读它们。
如果你写:
sub tester
{
return ($_[0] < 10) ? "You're a young'un" : "You're an oldie";
}
然后你会得到你期望的结果。
这是一个优先事项。
($_[0] < 10) ? ($return = "youre a youngin") : ($return = "youre an old fart");
...效果更好。
但老实说,没有一个认真的 Perl 程序员会这样写。 首先,他们会将以下内容放在程序的顶部:
use warnings;
use strict;
其次,他们会将论点放入本地:
sub tester {
my $arg = shift;
第三,他们会以以下两种方式之一编写条件:
if ($arg < 10) {
$return = "you're a youngin";
}
else {
$return = "you're an old fart";
}
如果他们来自 Lisp 背景,他们可能会省去 $return 变量而只写:
return $arg < 10 ? "you're a youngin" : "you're an old fart";
基本上,运算符优先级。
我相信$return;
是语法错误。 您不需要声明它 - perl 和 php 中的变量是无范围的。
此外=
优先于?:
因此您需要将()
添加到两个分配中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.