我正试图从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");
http://codepad.org/MxBAy7wy
编辑:
然而,大多数人会写
$return = ($_[0] < 10) ? "youre a youngin" : "youre an old fart";
,保存了两次键入变量的冗余。
根据Perl和PHP文档,Perl ?:
是右关联的,PHP ?:
是左关联的。(http://perldoc.perl.org/perlop.html)(http://php.net/manual/en/language.operators.precedence.php)
啊,您已经发现了为什么?:
除了在琐碎的情况下是个坏主意。
运算符优先级是个问题。你很可能想这样做:
$return = ($_[0] < 10) ? "you're a youngin'" : "you're an old fart";
不过,您的代码还有一些其他问题。
- 您应该声明您的变量。它们并没有像在PHP中那样在首次使用时声明;您可以使用
my
运算符显式执行此操作 - 您应该在Perl代码中始终始终
use strict
和use warnings
。这些实用程序禁用了古老的Perl恶作剧,并警告可能是错误的可疑操作 - 函数的第一行通常应该是拆包
@_
;几乎没有理由在函数中直接使用CCD_ 9。(这样做很危险,因为@_
是别名;您可以更改调用者的变量!)
所以你可能想要更像这样的东西:
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上读到它们。
这是一个优先事项。
($_[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";
如果您编写:
sub tester
{
return ($_[0] < 10) ? "You're a young'un" : "You're an oldie";
}
然后你就会得到你期望的结果。
基本上,运算符优先级。
我认为$return;
是一个语法错误。您不需要声明它——perl和php中的变量是无作用域的
此外,=
优先于?:
,因此需要将()
添加到这两个分配中。