なぜ PHP の三項演算子は左結合なのか
PHP の三項演算子が左結合で使いにくいという話題についてです。
次のプログラムは大抵の言語では one を表示するのですが、PHP では two になってしまいます。
<?php $var = 1; echo ($var == 1 ? 'one' : $var == 2 ? 'two' : 'three') . "\n";
三項演算子が左結合なので、このコードは次のように解釈され、
<?php $var = 1; echo (($var == 1 ? 'one' : $var == 2) ? 'two' : 'three') . "\n";
文字列 'one' は真偽値としては true になるので、結果的に 'two' が戻されるというわけです。
このような言語仕様になっている理由が気になったので、探してみました。
Bug #61915 incorrect associativity of ternary operator
https://bugs.php.net/bug.php?id=61915
[2012-05-02 22:38 UTC] johannes@php.net
Yes, this was an oversight when the language was defined and is documentedlike that on http://php.net/ternary (see the last note). Unfortunately we can't fix this without breaking code, which depends on the current order, in a non-obvious way.
どうやら PHP の言語が定義されたときの oversight だということです。そこで oversight という単語の意味を調べてみました。
http://ejje.weblio.jp/content/oversight
oversight【名詞】
【不可算名詞】 [具体的には 【可算名詞】] 見落とし,手落ち.
えーーと。。。
さて。上記のバグレポートにも書かれていますが、ここの left と right を書き間違えているのですね。行番号がバグレポートのものと違っているのは、PHP のバージョン違いだと思います。私はまだ PHP 5.3 を使っているので、今回も 5.3.22 で調べました。
$ diff zend_language_parser.y{-,} 59c59 < %left '?' ':' --- > %right '?' ':'
ここを書き直して make し直せば、たしかに期待される結果が返ってくるようになりました。