ワレハ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以外にはそうそう無いのいではないかと思います。