Skip to content

Instantly share code, notes, and snippets.

@LawnGnome
Created February 6, 2015 01:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save LawnGnome/354ca07f1799ff88fc35 to your computer and use it in GitHub Desktop.
Save LawnGnome/354ca07f1799ff88fc35 to your computer and use it in GitHub Desktop.

In no particular order, my issues with this RFC:

The declare switch

Adding the cognitive overhead for each file for developers to have to remember whether they have to cast a value before passing it to a function or if PHP will automagically do that for them is a bad thing. Of course, in a small, well compartmentalised file, or a single developer code base, it wouldn't be a problem. Unfortunately, a lot of PHP projects aren't that tidy. (Probably most of them, in fact.)

I also disagree with the comparisons that have been drawn on Internals between declare(strict_types=1), use strict, and from __future__ import foo statements. They're not the same thing at all:

  • use strict is ultimately about code quality — am I doing something dumb?
  • from __future__ import foo is ultimately about features — yes, I want to opt-in for the new shiny.
  • declare(strict_types=1) isn't either of those, although it might superficially appear so — what it's really about is "I reject your philosophy and substitute my own" in terms of typing.

There are structural decisions we can and should let our users make. I believe this isn't one of them: allowing users to fundamentally change the typing semantics of a language on a module-by-module level is, in my opinion, insanity. Languages have to be opinionated about this sort of issue: if they weren't, there'd only be one programming language and it would have 800 switches to configure before you could write a line of code. This sort of decision is the whole point of designing a language: abdicating it by providing a switch is effectively us shrugging and saying "sure, whatever, we don't care, so now we'll make you care".

Strong typing

This ties into the previous point: for scalars, PHP has never been a strongly typed language. I was once on the train of strict typing being universally better — if you know that you always have an integer, you never have to worry about a bad conversion, right? And, if I was designing a language from scratch, I'd probably still feel that way.

That language wouldn't be PHP, though. PHP is unapologetically weakly typed from top to bottom. Designing a feature to break that would be bad enough. Designing a feature to optionally break that is insidious. If you care about whether the zval IS_STRING, you can check that today. Encouraging our users to care goes against the entire philosophy of the language.

To be clear: yes, we have problems in our type conversion matrix. The fact that "21 Jump Street" == 21 is an issue (particularly because it's silent), and we should be talking about that. But strong typing is not the solution.

Caller versus callee

Making the caller responsible for choosing the type behaviour is a clever hack. (No pun intended, Facebookers.) I find the idea intriguing from an academic perspective. Unfortunately, as with the above point, this isn't consistent with PHP as a language that's existed for 20 years and had type hinting in its current form for over 10 years. If we accept this, then we only widen the gap between scalar values and array/object ones: for one set of type declarations, the behaviour is determined entirely by the callee, and for another, it's determined by both the callee (via the type hint) and the caller (whether it will be converted or not).

So what do we do for 7.0?

From where I sit, we had a good solution: it was the 0.1 version of this RFC. It behaved like PHP should behave, respected PHP's long standing scalar type handling and conversion rules, but most importantly, it solved the actual problem scalar type hints are supposed to solve in the simplest possible way:

Can I guarantee that my function that expects an integer will really get an integer?

I don't think that adding complexity on top of that helps anyone in the long run. Yes, we get to tick some extra boxes — "we support strong typing", "we support weak typing", "we put the user in control" — but at the cost of having a language that not only supports, but advertises multiple, inconsistent behaviours, requires users to be aware of conversion minutiae that they shouldn't have to be mindful of, and doesn't do anything to solve the actual problem above.

@elazar
Copy link

elazar commented Feb 6, 2015

I think we're mostly in agreement about this. There are two things I'd like to point out, though:

  1. I don't think the ability to check scalar types in function bodies today is a good reason not to have scalar type hints. A similar argument could have been made for class typehints before those were added, yet here we are. Both are, or at least really should be, merel syntactic sugar for a feature that already exists, albeit in a more verbose form.

  2. I agree that allowing the caller to determine type hinting behavior is a bad idea, and tend to think that we got rid of call-time pass-by-reference in 5.4 based on a similar principle.

@LawnGnome
Copy link
Author

  1. Nor do I. I probably worded that badly. 😃 I was only trying to make the point that the less common "I really need strict type checks because reasons" case can be supported with boilerplate, therefore I don't think we should support that specific case with syntactic sugar.
  2. That's a really good comparison, and one I didn't consider. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment