信じられないほどのパフォーマンスに加えて、PHP7の興味深い点の1つは、オプションの「strict」モードと組み合わせた
スカラー型ヒントの導入です。 RFCを読んでいると、例の中のPHPコードが
Hackと非常によく似ていることに気付きました。 PHP7とHackの両方で同じコードを実行するとどうなりますか? 2つの違いは何ですか? これが私が学んだことです。
設置
次の結果を取得します。
$ php --version PHP 7.0.0-dev (cli) (built: Apr 23 2015 01:12:36) (DEBUG) Copyright (c) 1997-2015 The PHP Group Zend Engine v3.0.0-dev, Copyright (c) 1998-2015 Zend Technologies with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies
$ hhvm --version HipHop VM 3.8.0-dev (rel) Compiler: heads/master-0-gd71bec94dedc8ca2e722f5619f565a06ef587efc Repo schema: fa9b8305f616ca35f368f3c24ed30d00563544d1
ソースファイルの開始タグを変更してHHVMでPHPコードを
hhvm
するには、フラグ
-vEval.EnableHipHopSyntax=true
hhvm
して
hhvm
を
hhvm
-vEval.EnableHipHopSyntax=true
。
いくつかの例
簡単なコードを考えてみましょう:
<?php declare(strict_types=1); function myLog(string $message): string { return $message; } function add(int $a, int $b): int { myLog($a + $b); return $a + $b; } $result = add(1, 3); echo $result;
PHP7での実行は以下を返します:
Fatal error: Argument 1 passed to myLog() must be of the type string, integer given, called in /home/vagrant/basic/main.php on line 9 and defined in /home/vagrant/basic/main.php on line 4
よさそう! PHP7は、文字列を予期し、対応するエラーメッセージを生成する関数に整数(
$a + $b
)を渡すと正しく述べています。 HHVMの言うことを見てみましょう:
Catchable fatal error: Argument 1 passed to myLog() must be an instance of string, int given in /home/vagrant/basic/main.php on line 6
いくつかの違いがあります。
- HHVMはこれを「キャッチ可能な」致命的エラーと呼びます。 興味深いことに、 RFCは、エラーが実際にHHVMと一致するはずだと述べています。
- HHVMは、エラーが6行目にあり、PHPが問題が9行目に発生したことを報告します。そのような場合、PHPアプローチを好むでしょう。
<?hh declare(strict_types=1); function myLog(string $message=null): string { if ($message === null) { return ''; } else { return $message; } } echo myLog("Hello world!\n"); echo myLog();
PHPは喜んでコードを実行します。 ハックはエラーを返します:
/home/vagrant/nullable/main.php:4:16,21: Please add a ?, this argument can be null (Typing[4065])
ハックでは、値がnullのデフォルト引数を使用できません。 「オプションの引数」の概念と「デフォルト値を設定できる必須の引数」を混同しない(詳細については、本
Hack and HHVMをお読みください)。 言語では、引数を
nullable
することを提案しています。
<?hh declare(strict_types=1); function myLog(?string $message=null): string { if ($message === null) { return ''; } else { return $message; } } echo myLog("Hello world!\n"); echo myLog();
もっと複雑なものを試してみましょう。 PHPでタイピングを混ぜるとどうなりますか? ファイルの先頭にある厳密モードの定義は、HHVMでは効果がないことに注意してください。
<?php function add(int $a, int $b): int { myLog($a + $b); return $a + $b; }
<?php declare(strict_types=1); function myLog(string $message): string { return $message; }
<?php require 'add.php'; require 'logger.php'; $result = add(1, 3); echo $result;
$ php main.php 4 $ hhvm -vEval.EnableHipHopSyntax=true main.php Catchable fatal error: Argument 1 passed to myLog() must be an instance of string, int given in /home/vagrant/separate_files_mixed/lo
logger.php
厳密モードが有効になっていますが、PHPでは
logger.php
厳密ファイルからintを渡すことができます。 この場合、HHVMは例外をスローします。
add.php
な型指定モードにするとどうなりますか:
Fatal error: Argument 1 passed to myLog() must be of the type string, integer given, called in /home/vagrant/separate_files_mixed/add.php on line 5 and defined in /home/vagrant/separate_files_mixed/logger.php on line 4
それは良いです。 厳密モードは、関数を宣言するファイルが別の方法で示唆している場合でも、指定されたファイルでのみ有効です。 しかし、厳密関数から非厳密関数を呼び出すとどうなりますか? 実装のために、ファイルに次の値を設定します。
logger.php - non-strict add.php - strict
Fatal error: Argument 1 passed to myLog() must be of the type string, integer given, called in /home/vagrant/separate_files_mixed/add.php on line 5 and defined in /home/vagrant/separate_files_mixed/logger.php on line 3
適切なヘッダーを持つファイルで宣言されている関数から呼び出された場合、関数は強く型付けされていることがわかります。 ただし、これは直接呼び出しにのみ影響します。
main.php
強く型付けされ
main.php
宣言
main.php
、
log()
渡す型の不一致にもかかわらず、PHPは喜んで4を返し
log()
。
ハックでは、比率は反対です。 HHVMが非厳密モードでmain.phpを実行し、ロガーが(ファイルの先頭に
hh
タグを付けて)Hackで記述されている場合、呼び出されたファイルがHackで記述されていなくても型エラーが発生します。
Catchable fatal error: Argument 1 passed to myLog() must be an instance of string, int given in /home/vagrant/separate_files_mixed/logger.php on line 5
HackとPHPタイプシステムのもう1つの興味深い違いは、floatアノテーションです。 例を挙げましょう:
<?php declare(strict_types=1); function add(float $a, float $b): float { return $a + $b; } echo add(1, 2);
実行すると、PHPで
3
が返されますが、厳密な入力モードが有効になっているにもかかわらず、
float
注釈
float
付けられた場所に
int
を渡します。 その理由は、PHP7では、strictモードが有効になっている場合、
拡大プリミティブ変換がサポートされているためです。 これは、安全な変換が可能な
場合 (ほとんどの場合)、
float
として注釈が付けられたパラメーターが
int
値
を持つことができることを意味します。 HHVMはこの動作をサポートせず、上記のコードを実行するときに型エラーをスローします。
Catchable fatal error: Argument 1 passed to add() must be an instance of float, int given in /home/vagrant/main.php on line 6
私が見逃した他の違いがある場合は、下のコメントでお知らせください。 このトピックをもっと深く研究したいと思います。
おわりに
Hackは多くのチップをサポートしていますが、PHP7は
nullable 、
mixed 、void戻り値、
collection 、
asyncなどをサポートしていません。それでも、PHP7の新しい厳格モードによって達成されたセキュリティと読みやすさに非常に満足しています。
Hackでいくつかの小さなプロジェクトを書いた後、型自体がHackを快適にするのではなく、言語が開発者とマシンの間で作成するフィードバックそのものであることに気付きました。
エディターにHackの型チェック統合が存在するということは、ファイルを保存した後、コードベース全体が一瞬で分析されることを意味します。 私が犯した愚かで明白な間違いはすぐに断ち切られます。 ますます、関数の戻り値について考えるのではなく、単純にコードを書いて、明らかなオプションを提案するようになりました。 エラーがある場合、エディターはすぐに私に通知します。 いくつかの小さな編集があり、先に進むことができます。
PHPは、マシンと開発者の間で常に密接なフィードバックを促進しています。 ファイルを保存し、ブラウザでページを更新し、結果が得られるまで繰り返します。 速くて便利。 ただし、Hackでの型チェックにより、さらに高速になります。 新しいPHPで強力な型付けを行うために、IDE /エディターで同様の機能が見られることを楽しみにしています。