三項演算子の実行順序

phpには、三項演算子の興味深い機能があります-具体的かつ一意の実行順序。

$ python -c "print 1 if true else 2 if true else 3 if true else 4 if true else 5 "
1

$ node -e " true ? 1 : true ? 2 : true ? 3 : true ? 4 : 5 "
1

$ perl -e "print true ? 1 : true ? 2 : true ? 3 : true ? 4 : 5 "
1

$ ruby -e "print true ? 1 : true ? 2 : true ? 3 : true ? 4 : 5 "
1

$ php -r "print true ? 1 : true ? 2 : true ? 3 : true ? 4 : 5 ;"
4
JavaおよびC ++も1を返します


違いは何ですか?


私は長い間この興味深いニュアンスを知っていましたが、昨日、オープンソースの1つでエラーを見つけました。著者は明らかにこのニュアンスを知らず、捕まってしまいました。 したがって、この記事は単なる警告です。 結局のところ、プログラマーが他の言語と同じ動作をphpに期待する場合、彼はがらくたに陥る可能性があります。

この手法は、条件に応じて値を設定するのに非常に便利です。 エレガントなif-else交換。 例:
 value = isCondFirst() ? valueFirst() : isCondSecond() ? valueSecond() : isCondThird() ? valueThird() : valueDefault(); /**********  **********/ if (isCondFirst()) { value = valueFirst(); } else if (isCondSecond()) { value = valueSecond(); } else if (isCondThird()) { value = valueThird(); } else { value = valueDefault(); } 


間違いを避ける方法は?


最初の方法は、PHPで三項演算子を使用しないことです。
2番目は、括弧を使用して実行順序を直接示すことです。

$ php -r "print true ? 1 : ( true ? 2 : ( true ? 3 : ( true ? 4 : 5 )));"
1

Lispを連想させるものですよね?

なぜこのように起こるのでしょうか?


例としてJavaScriptとPHPを使用して、三項演算子の実行順序を見てみましょう
各言語がどのように機能するかを理解するために、2つのテストスクリプトを作成します。

念のため、 $foo = $lambda('fooMsg', 'fooReturn')$fooは、呼び出されたときにコンソールにメッセージ'fooMsg'表示し、値'fooReturn'を返す関数が含まれます

$ cat ternary. js
 var lambda = function (logMsg, returnValue) { return function () { console.log(logMsg); return returnValue; }; }; var cond = { first : lambda('cond.first' , true), second: lambda('cond.second', true), third : lambda('cond.third' , true) }; var value = { first : lambda('value.first' , 'first'), second : lambda('value.second' , 'second'), third : lambda('value.third' , 'third'), default: lambda('value.default', 'default') }; console.log( 'result: ', cond.first() ? value.first() : cond.second() ? value.second() : cond.third() ? value.third() : value.default() ); 


$ node ternary. js
cond.first
value.first
result: first


$ cat ternary. php
 <?php $lambda = function ($logMsg, $returnValue) { return function () use ($logMsg, $returnValue) { echo $logMsg . PHP_EOL; return $returnValue; }; }; $cond = array( 'first' => $lambda('cond.first' , true), 'second'=> $lambda('cond.second', true), 'third' => $lambda('cond.third' , true), ); $value = array( 'first' => $lambda('value.first' , 'first'), 'second' => $lambda('value.second' , 'second'), 'third' => $lambda('value.third' , 'third'), 'default'=> $lambda('value.default', 'default'), ); echo 'result: ' . ( $cond['first']() ? $value['first']() : $cond['second']() ? $value['second']() : $cond['third']() ? $value['third']() : $value['default']() ) . PHP_EOL; ?> 

$ php ternary. php
cond.first
value.first
value.second
value.third
result: third


この結果のどちらを結論付けることができます。 Javascriptは、三項演算子を非常に論理的に解析します。 最初に左端の条件をチェックします。 trueの場合、最初のコロンの後の左部分を実行し、trueでない場合は右を返します。
 (cond.first() ? value.first() : (cond.second() ? value.second() : (cond.third() ? value.third() : (value.default())))); /******** * ===> */ true ? 'value.first' : /* ignored */; 


PHPはオリジナルだと考えています。

 ( ( cond.first() ? value.first() : cond.second() ) ? value.second() : cond.third() ) ? value.third() : value.default(); /******** * ===> */ ( ( 'value.first' ) ? value.second() : cond.third() ) ? value.third() : value.default(); /******** * ===> */ ( 'value.second' ) ? value.third() : value.default(); /******** * ===> */ 'value.third' 


公式マニュアルで確認されていること:
 $a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 


おわりに


一般に、PHPは「最高の側面から」再び姿を現しましたが、問題は重大とはほど遠いものです。 主なことは、それについて知り、PHPの三項演算子に注意することです。

Source: https://habr.com/ru/post/J114899/


All Articles