y_uti のブログ

統計、機械学習、自然言語処理などに興味を持つエンジニアの技術ブログです

なぜ 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 し直せば、たしかに期待される結果が返ってくるようになりました。