Scalar typing in the PHP world
Some history
PHP has traditionally taken a loose approach to types, trying to make things "just work" in almost all circumstances. A simple session in the interpreter's interactive mode shows how accommodating it can be:
$ php -a
php > echo 1 + "1";
2
php > echo 1 + true;
2
php > echo 1 + "1with_extra_junk";
2
This flexibility undoubtedly makes PHP fun for some programmers to use; there is little of the messing around required by some other languages to keep the interpreter happy. Among other things, it allows the creation of library functions that can take a wide variety of types as parameters and do something (maybe even the right thing) with them.
But others would like to see things tightened down a bit. It would be nice, they argue, if a PHP function could count on the types of the arguments passed to it. That would enable certain kinds of errors to be caught by the interpreter; it would also make it easier to write static analyzers for the language that could be used for both correctness checking and performance improvements. These developers have made their case well enough that there is little controversy about adding some type checking; the problem arises when one tries to determine how much checking makes sense.
The specific issue at hand has to do with the passing of simple, scalar parameter types to functions — types like integers, floating-point numbers, strings, and booleans. The first attempt to add type hints for these parameter types was posted by Anthony Ferrara in 2012. It changed the function-definition syntax to look like this:
function f ((int) arg) {
// "arg" is guaranteed to be int here
}
This version implemented what has been termed "weak" typing, in that a non-integer argument passed to f() would be converted to the int type if possible. So floating-point numbers would be truncated, strings would be converted, etc. This proposal generated a lot of discussion that eventually bogged down; a year later, Anthony loudly bailed out of PHP development, strongly criticizing the environment found on the php-internals mailing list.
The discussion of a vote may be surprising to those who are not familiar with how the PHP community works. Perhaps uniquely among language-development communities, PHP decides issues of language design via a vote of the developers. Issues involving an actual change to the language are deliberately hard to pass; they require a ⅔ supermajority.
Weak or strong?
As the various versions of the proposal went by, the real point of contention became clear. Nobody seems to object to the idea of adding scalar type hints to function definitions; the real problem had to do with how strictly they would be enforced. The "strict typing" camp wants the interpreter to disallow all implicit type conversions; if f() is defined to require an integer argument, calls like f(1.0) or f("1") should generate an error. In this view of the world, if an API developer puts type declarations onto a function, that function must be called with parameters of exactly the specified type.
The arguments for strict checking are fairly straightforward. It can catch errors that weak (or no) type checking will miss — the sort of nasty error that never happens on a developer's test system but which certain types of users can provoke easily. Strict checking lets API developers design their code with the knowledge that it will be called with the correct types. It also expands the range of static analysis options available, again turning up errors but also, it is said, opening the door to new optimization techniques.
On the other side, opponents of strong typing feel that it would drastically change the nature of the language. PHP has always allowed a high level of freedom in the mixing of types. Changing that for PHP 7 would create a language that, in their view, is not PHP. Among these folks, many of whom are core developers of the language, adding strong typing would seemingly be like trying to get Python developers to add braces or Perl developers to restrict themselves to "one way to do it." Opponents also worry that strict typing may just lead developers to write lots of casts, effectively taking away the benefits that strict typing is supposed to provide.
An attempt at compromise
Andrea appears to have despaired of ever bridging the gap between these two
factions; instead, she put together a new
proposal that tried to please everybody, then called for a vote. In the
call, she optimistically said "I don’t think there needs to be, or
will be, much further discussion
"; that is not how things turned
out.
The new scalar typing mechanism is still weakly typed, but with a twist. A PHP developer can add a line like this to their code:
declare(strict_types=1);
The effect of this line will be to turn on strict scalar type checking for the rest of the source file in which it is found. Library authors can add types to their function definitions; they can even turn on strict checking within the library with the above option. But it will be the author of the calling code who decides whether or not to add that line to their own code and turn on strict checking for their program.
In theory, this mechanism gives everybody what they want; developers who want to work in a strict-checking environment can have it, while those who want weak typing get it by default. In practice, this approach appears to have pleased almost nobody. Proponents of strong typing would rather see it enabled as a mandatory thing; they want callers of their functions to be required to pass the correct types. Opponents, instead, see it as a way of sneaking an alien concept into the language. PHP creator Rasmus Lerdorf also worries that it could end up breaking a lot of code and generally leading to surprising results.
To top it off, almost nobody seems to like the use of declare() which, among other things, can make it hard to tell which rules apply to a given segment of code. As Zeev Suraski put it:
Even the declare() option has proponents, though; Anthony returned to the fray to argue in its favor:
The genius of this proposal is that your code controls how you call other functions. So if you want your code to be strict, any function you call will be treated strictly. But if you don't want to be strict, then the functions you call will accept weakly.
The current vote is scheduled to end on February 19. As of this
writing, the results suggest
that proposal might just pass with something very close to the required
supermajority. In theory, that should put this long-lived debate to rest;
long experience suggests, though, that an issue this contentious will not
be resolved quite so easily.
The LWN site is currently under high scraper load, so comment display has been suppressed for anonymous users. If you are a human, you may read the comments by clicking the button below:
Note: you can avoid this step in the future by logging into your LWN account.
