PHP7とハックタイプシステムの比較


信じられないほどのパフォーマンスに加えて、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してhhvmhhvm -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 

いくつかの違いがあります。

 <?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.phplog()渡す型の不一致にもかかわらず、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はnullablemixed 、void戻り値、 collectionasyncなどをサポートしていません。それでも、PHP7の新しい厳格モードによって達成されたセキュリティと読みやすさに非常に満足しています。

Hackでいくつかの小さなプロジェクトを書いた後、型自体がHackを快適にするのではなく、言語が開発者とマシンの間で作成するフィードバックそのものであることに気付きました。 エディターにHackの型チェック統合が存在するということは、ファイルを保存した後、コードベース全体が一瞬で分析されることを意味します。 私が犯した愚かで明白な間違いはすぐに断ち切られます。 ますます、関数の戻り値について考えるのではなく、単純にコードを書いて、明らかなオプションを提案するようになりました。 エラーがある場合、エディターはすぐに私に通知します。 いくつかの小さな編集があり、先に進むことができます。

PHPは、マシンと開発者の間で常に密接なフィードバックを促進しています。 ファイルを保存し、ブラウザでページを更新し、結果が得られるまで繰り返します。 速くて便利。 ただし、Hackでの型チェックにより、さらに高速になります。 新しいPHPで強力な型付けを行うために、IDE /エディターで同様の機能が見られることを楽しみにしています。

Source: https://habr.com/ru/post/J259209/


All Articles