ワレハget_debug_type、コンゴトモヨロシク…
PHPにはプリミティブ型名を取得するgettypeと、オブジェクトのクラス名を返すget_classという関数が存在します。
_があったりなかったりと命名の不統一も気になりますが、それよりgettypeはオブジェクトに使うとobjectしか返さず、get_classをプリミティブ型に使うとE_WARNINGが発生します。
いや、プリミティブ型であればintとかの型が欲しいし、オブジェクトならPDOとかの型が欲しいんだ、という問題に対する答えはありませんでした。
というわけで両者を合体させたget_debug_typeというRFCが提出されました。
PHP RFC: get_debug_type
proposal
このRFCは、指定された変数の型を返す新しい関数、get_debug_typeを追加する提案です。
これは、配列で来る値など、変数の型に基づいた既存のチェック方法では対応できないパターンを置き換えるためのものです。
$bar = $arr['key'];
if (!($bar instanceof Foo)) {
// もっとも単純な例。しかしgettypeは"integer"を返すので、正しい型にしたいなら"int"に変換するなどが必要。
throw new TypeError('Expected ' . Foo::class . ' got ' . (is_object($bar) ? get_class($bar) : gettype($bar)));
}
// 今後はこう書ける
if (!($bar instanceof Foo)) {
throw new TypeError('Expected ' . Foo::class . ' got ' . get_debug_type($bar));
}
$bar->someFooMethod();
この関数は、正しい型名を返すという点でgettypeと異なります。
"integer"ではなく"int"を返し、クラスもクラス名に変換します。
次の表は、いくつかの値に対してgettypeとget_debug_typeが返す値を比較したものです。
| 値 | get_debug_type() | gettype() |
|---|---|---|
| 0 | int | integer |
| 0.1 | float | double |
| true | bool | boolean |
| false | bool | boolean |
| "hello" | string | |
| [] | array | |
| null | null | NULL |
| Foo\Bar | Foo\Bar | object |
| 無名クラス | class@anonymous | object |
| リソース | resource (xxx) | resource |
| 閉じたリソース | resource (closed) |
Backward Incompatible Changes
なし。
Proposed PHP Version(s)
PHP8.0
Implementation
投票
投票は2020/03/26まで、2/3の賛成で受理されます。
このRFCは賛成42、反対3で受理されました。
感想
Mark Randallは最初はgettypeがクラス名も返すようにしようとしたものの、Nikitaから「新しい関数にしてくれ」と言われてget_debug_typeを作ったようです。
まあ、これまでobjectとしか言わなかったgettypeがいきなり色々な型を喋り出したら困るところも出そうですからね。
ということで、今後は型の取得はget_debug_typeに一本化できそうです。
手間を省くための定型処理を言語機能に取り込むことは、他の言語でも多々起きていることです。
たとえばJavaScriptのasync/awaitはPromiseの糖衣にすぎず、async/awaitができることは全てPromiseでもできるので、究極的にはasync/awaitは不要です。
しかし非同期処理を楽に書けるようにするために言語仕様に取り込まれました。
糖衣構文の取り込み自体は、このようにさほど珍しいことでもありません。
しかし、str_containsとかis_countableとか、他言語であれば「自分で書け」と言われそうな極端に簡単な構文まで言語仕様に取り込んでしまう言語は、PHP以外にはそうそう無いのいではないかと思います。