簡體   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