📜 ⬆️ ⬇️

Comparison of PHP7 and Hack type systems


One of the interesting things about PHP7, besides the incredible performance, is the introduction of scalar type-hinting in combination with the optional “strict” mode. When reading the RFC, I noticed that the PHP code in the examples looks very similar to Hack . What if you run the same code in both PHP7 and Hack? What is the difference between them? That's what I learned.

Installation


Get the following result:

$ 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 

In order to execute PHP code in HHVM without changing the opening tags in the source files, execute hhvm with the -vEval.EnableHipHopSyntax=true flag.

Some examples


Consider simple code:
')
 <?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; 

Its execution in PHP7 will return:

 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 

Looks nice! PHP7 correctly says that we are passing an integer ( $a + $b ) to a function that expects a string, and gives the corresponding error message. Let's see what HHVM says:

 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 

There are a couple of differences:

 <?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 happily executes the code. Hack returns an error:

 /home/vagrant/nullable/main.php:4:16,21: Please add a ?, this argument can be null (Typing[4065]) 

Hack does not allow us to have a default argument with a null value, since It does not confuse the concept of an “optional argument” with a “mandatory argument that allows you to have a default value” (For more on this, read Hack and HHVM ). The language prompts you to make the argument 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(); 

Let's try something more complicated. What happens if we mix typing in PHP? Note that the definition of the strict mode at the top of the file has no effect in 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 

For logger.php strict mode is enabled, but PHP allows you to transfer int to it from a nonstrict file. HHVM in such a case throws an exception. What happens if we put add.php in strong typing mode:

 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 

That's better. Strict-mode is valid only in those files where it is specified, even if the file declaring the function implies otherwise. And what happens if we call the non-strict function from the strict function? To implement, I set the following values ​​for the files:

 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 

It turns out that the function is strictly typed if it is called from a function that is declared in the file with the appropriate header. However, this only affects direct calls. If we declare main.php strictly typed, PHP will happily return 4 to us, despite the type mismatch that we pass to log() .

In Hack, the ratio is the opposite. If HHVM performs main.php in a non-strict mode, and the logger is written in Hack (with the hh tag at the top of the file), we still get a type error even though the file being called is not written in 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 

Another interesting difference between the Hack and PHP type systems is the float annotation. Take an example:

 <?php declare(strict_types=1); function add(float $a, float $b): float { return $a + $b; } echo add(1, 2); 

When executing in PHP, it returns 3 , although we pass an int at the place where the float annotated and despite the fact that the strong typing mode is enabled. The reason is that PHP7 supports widening primative conversion with strict mode enabled. This means that parameters annotated as float can have an int value when safe conversion is possible (almost always). HHVM does not support this behavior and throws a type error when executing the above code:

 Catchable fatal error: Argument 1 passed to add() must be an instance of float, int given in /home/vagrant/main.php on line 6 

If there are any other differences that I have missed, please let us know in the comments below. I would really like to study this topic more deeply.

Conclusion


While Hack supports many chips, PHP7 does not support nullable , mixed , void return values, collections , async , etc. But I am still very pleased with the security and readability achieved by the new PHP7 strict-mode.

After writing a couple of small projects on Hack, I realized that it was not the types themselves that make Hack enjoyable, but the very feedback that the language creates between the developer and the machine. The presence of type checking for Hack in my editor means that the entire code base is analyzed in a fraction of a second after I save the file. Immediately cut off the stupid or non-obvious errors that I made. I increasingly began to catch myself not thinking about the returned values ​​of functions, I just write code on a whim, assuming obvious options. If there is an error, the editor will immediately inform me. A couple of small edits and you can move on.

PHP has also always promoted close feedback between the machine and the developer. Save the file, refresh the page in the browser, repeat to achieve the result. Quick and convenient. But type checking in Hack makes it even faster. I look forward to the emergence of similar functionality in the IDE / editors for strong typing in the new PHP.

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


All Articles