【PHP8】8進数も基数表示を明記したい
PHPの数値リテラルは、いくつかの基数をサポートしています。
$a = 16; // 10進数
$a = 0x10; // 16進数
$a = 0b00010000; // 2進数
$a = 020; // 8進数
8進数だけおかしくない?
ということでExplicit octal integer literal notationというRFCが提出されました。
Explicit octal integer literal notation
Introduction
PHPの8進数リテラル表記は、"016" == 016
がfalseになるなどよくわからない結果になることがあります。
これは016
が8進数であり、10進数でいう14
になるからです。
この表記は、Java、C、C#、Golang、Haskellその他諸々の言語と同じ規則であり、たしかに確立された文法ではあります。
一方Python・JavaScript・Rustは0o
表記のみをサポートしています。
PHPのoctdecやbase_convert関数は、実はしれっと0o
表記をサポートしていたりします。
Proposal
16進数の0x
、2進数の0b
と同じように、8進数リテラルを表す接頭辞0o
をサポートします。
0o16 === 14; // true
0o123 === 83; // true
016 === 0o16; // true
Behaviour of numeric strings
PHP7.0では、文字列での基数表記はサポートされていません。
数値型文字列における基数サポートは、複雑で混乱を招くため却下されました。
However supporting octal numbers is not possible, because handling the string '0123' as the number 83 would be highly unexpected for end users of an application.
8進数のサポートは不可能です。
なぜなら文字列'0123'
を数値83
と解釈することは、ユーザにとって全く予期せぬ結果になります。
従ってこのRFCも、文字列に対しては何の影響も及ぼしません。
'0o16'
は今後もただの文字列です。
Backward Incompatible Changes
互換性のない変更はありません。
Proposed PHP Version(s)
PHP8.x
RFC Impact
To Existing Extensions
GMPエクステンションは8進数表記への対応が必要。
FILTER_VALIDATE_INTフラグのFILTER_FLAG_ALLOW_OCTALは対応が必要。
To Opcache
特になし。
Unaffected PHP Functionality
現在の、暗黙の8進数表記の動作に変更はありません。
Future Scope
・いずれ暗黙の8進数表記を非対応にする。
・数値型文字列において進数表記をサポートする。
Patches and Tests
GitHubには既にパッチが上がっています。
感想
えっマジかよ。
マジだった。
var_dump(octdec('020')); // 16
var_dump(octdec('0o20')); // 16
var_dump(base_convert('020', 8, 10)); // "16"
var_dump(base_convert('0o20', 8, 10)); // "16"
マニュアルにもユーザノートにも一切書かれていない超絶秘密機能が隠されていたとはびっくりだよ。
こういうのって、探せば他にもあるかもしれませんね。
さて、このRFCはまだ提出されただけです。
今後受理されるか却下されるかは、投票を待たなければいけません。
しかし特に反対するような理由もないだろうし、さらにSara GolemonとNikitaの二人が早々と賛成しているので、まず間違いなく通るでしょう。
そしてそんなに重たい内容でもなさそうなので、おそらくPHP8.1あたりでさくっと導入されると思います。
今後は以下のようにわかりやすく表記できるようになることでしょう。
$a = 16; // 10進数
$a = 0x10; // 16進数
$a = 0b00010000; // 2進数
$a = 0o20; // 8進数
0とoがわかりにくいな。
Discussion