繁体   English   中英

perl 中的三元运算符在语句中分配变量时产生意外结果

[英]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");

http://codepad.org/MxBAy7wy

编辑:

然而,大多数人会写

$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";

不过,您的代码还有一些其他问题。

  • 你应该声明你的变量。 它们没有像 PHP 那样在首次使用时声明; 您可以使用my运算符明确执行此操作。
  • 您应该始终、始终、始终在 Perl 代码中use strictuse warnings 这些编译指示禁用了古老的 Perl 恶作剧,并警告可能是错误的可疑操作。
  • function 的第一行通常应该是解包@_ 没有什么理由直接在 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM