條件(三元)運算子表明三元運算子是if的替代。else。
我一直這么認為,但最近我有一個邏輯問題。
考慮一下這個簡短的除錯程序:
DB<1> $s='X'/span>
DB<2> 1 ? $s .= '_' : $s = '_' ?
DB<3> x $s
0 '_' $s
因此,如果1為真,那么運算式$s .='_'應該被評估(而不是$s='_')。
但是為什么$s在最后只是'_'?
uj5u.com熱心網友回復:
三元條件運算子(?:)比賦值運算子(=)有更高的優先級(Perl's運算子的優先級表可以在perlop的Operator Precedence and Associativity部分找到。) 因此,這一行
1 ? $s .= '_' : $s = '_' ?
被Perl決議為
(1 ? ($s .= '_') : $s) = '_'
(你可以通過運行perl -MO=Deparse <你的程式>來自己檢查)
還要注意的是,$s .= '_'回傳$s,并在末尾添加_,而且這個$s可以被賦值(用技術術語來說,它是一個lvalue)。這在perlop的Assignment Operators部分有記錄:
與C語言不同,標量賦值運算子產生一個有效的lvalue。修改一個賦值等同于進行賦值,然后修改被賦值的變數。
所以,基本上,你的代碼正在做
($s .= '_') = '_'。
這等同于
$s .= '_';
$s = '_';
uj5u.com熱心網友回復:
這是一個操作者優先的問題。
$ perl -MO=Deparse,-p -e '
> $s='X'。
> $t=1;
> $t ? $s .= '_' : $s = '_'。
> print $s'/span>
($s = 'X') 。
($t = 1) 。
(($t ? ($s .= '_') : $s) = '_') 。
print($s)。
-e 語法確定
無論三元組條件是真還是假,最終$s被設定為"_"。
為了實作你的意圖,你需要添加至少一組小括號:
1 ? $s .= '_' : ($s = '_') 。
uj5u.com熱心網友回復:
條件運算子只評估必要的東西,但你有一個優先級的問題。
首先,條件運算子確實保證使用短路評估,這意味著它只評估必要的東西。
$ perl -M5.010 -e'
sub f { say "f" }
sub g { say "g" }
$ARGV[0] ? f() : g();
' 0
f
$ perl -M5.010 -e'
sub f { say "f" }
sub g { say "g" }
say $ARGV[0] ? f() : g();
' 1
g
對于E1 || E2、E1或E2、E1 && E2和E1和E2來說也是如此。它們只在必要時評估其右側的運算元。
$ perl -M5.010 -e'
sub f { say "f"; $ARGV[0] }
sub g { say "g"; $ARGV[1] }
say f() || g();
' 3 4
f
3
$ perl -M5.010 -e'
sub f { say "f"; $ARGV[0] }
sub g { say "g"; $ARGV[1] }
say f() || g();
' 0 4
f
g
4
這就是為什么你可以安全地評估 open(...) 或 die(...)。如果沒有短路,無論open是否成功,它都會評估die。
現在,讓我們解釋一下:
$s = "X"/span>; 1 ? $s .= "_" : $s = "_"; say $s; # _
這是一個優先級問題。上面的內容等同于
$s = "X"/span>; ( 1 ? ($s .= "_") : $s ) = "_"; say$s; # _
$s .= "_"回傳$s,所以條件運算子回傳$s,所以字串_被分配給$s。如果我們添加帕累斯來獲得所需的決議,我們會得到預期的結果。
$s = "X"/span>; 1 ? ($s .= "_") : ($s = "_"); say$s; # X_
替代方案:
$s = "X"/span>; $s = ( 1 ? $s : "" ) 。"_"; say$s; # X_
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/311325.html
標籤:
