PHP7 Gains Scalar Type Hints(wiki.php.net)
wiki.php.net
PHP7 Gains Scalar Type Hints
https://wiki.php.net/rfc/scalar_type_hints_v5#vote
143 comments
Well an obvious reason is all the PHP site that have already been written, are crucial components in many businesses, and cannot be upgraded to Hack. Those sites' authors may still want access to all that good stuff.
In fact, this kind of feature may make it easier to convert those applications to Hack in the future.
In fact, this kind of feature may make it easier to convert those applications to Hack in the future.
You can freely mix Hack code and PHP code on the HHVM, calling functions and classes defined in any PHP file inside you Hack app. Then you can slowly evolve the codebase to contain more and more Hack and less and less PHP.
That's the huge point that nobody seems to see.
But then again, considering how many other huge points PHP developers seem to miss in general, maybe it's better to just let Node.js eat the world :)
That's the huge point that nobody seems to see.
But then again, considering how many other huge points PHP developers seem to miss in general, maybe it's better to just let Node.js eat the world :)
In that case I take it all back! Sorry, I hadn't realised HHVM was so far along.
I think it is important for what Facebook has done to fork and bleed all over the edge of optimization. What needs to happen is that the best features to come out of that float up to the root language and are adopted as part of the standard.
PHP the language will always rely on PHP the brand being as ubiquitous as it is. The more that can be done to improve the language, the stronger the brand and the longer it will endure.
PHP the language will always rely on PHP the brand being as ubiquitous as it is. The more that can be done to improve the language, the stronger the brand and the longer it will endure.
Interesting that Rasmus voted a No for this.
Not really, I think. It was exactly as I expected.
I once attended a mini-conference where he did a talk about PHP history. After the talk, someone asked a question about strict typing. Rasmus really hold on to the web not having types (just passing strings, as have been pointed out in other comments here). I remember him saying something like "when the web have strict types, PHP will have it too".
I once attended a mini-conference where he did a talk about PHP history. After the talk, someone asked a question about strict typing. Rasmus really hold on to the web not having types (just passing strings, as have been pointed out in other comments here). I remember him saying something like "when the web have strict types, PHP will have it too".
This is actually quite revealing. Some people think that PHP is just used for the same small web pages it was used for 15 years ago.
Other people would like to use PHP more as a general computing language.
Having optional types takes nothing away from using PHP for simple web pages, but does make it easier to right analyzably correct programs.
The fact that the founder of a language doesn't want to see it grow is quite depressing.
Other people would like to use PHP more as a general computing language.
Having optional types takes nothing away from using PHP for simple web pages, but does make it easier to right analyzably correct programs.
The fact that the founder of a language doesn't want to see it grow is quite depressing.
He doesn't want this particular feature. Considering the amount that PHP has grown, he obviously does want it to grow.
So how do you go about using this in both PHP5 and PHP7 at the same time?
Do you need to run a pre-processor to strip them out of the code that runs on PHP5, while getting the benefit for testing on PHP7?
Trying it naively, PHP5 thinks you want to use a class called "int". And doesn't like the : for the return value.
Do you need to run a pre-processor to strip them out of the code that runs on PHP5, while getting the benefit for testing on PHP7?
Trying it naively, PHP5 thinks you want to use a class called "int". And doesn't like the : for the return value.
To explain the slightly horrible fact that there are two modes, strict and weak with strict mode being enabled on a per file basis; people just couldn't agree on whether the types should be strict or if they should use PHP's existing coercion rules. (Or even a 3rd new set of conversion rules, but lets ignore them).
Having an optional mode per file allows:
People who want to write code with strict types can do so. People who want to write code with weak types can do so. People who want to write code without these new fangled types can continue to do so.
All without any issues of compatibility between running code on the current version of PHP and what will be the next one, and without any compatibility issues for libraries that are solely written in one mode, being used in applications that are written in the other mode.
\o/
To be honest, I'm completely in the strict camp - but it's awesome that we've gotten a solution that should allow everyone to use the mode they want, without splitting the PHP ecosystem.
Having an optional mode per file allows:
People who want to write code with strict types can do so. People who want to write code with weak types can do so. People who want to write code without these new fangled types can continue to do so.
All without any issues of compatibility between running code on the current version of PHP and what will be the next one, and without any compatibility issues for libraries that are solely written in one mode, being used in applications that are written in the other mode.
\o/
To be honest, I'm completely in the strict camp - but it's awesome that we've gotten a solution that should allow everyone to use the mode they want, without splitting the PHP ecosystem.
The big benefit is you don't end up with "weakly-typed", "strongly-typed" and "untyped" APIs. There are just "typed" and "untyped" ones, and you can choose the behaviour that suits you best.
> To be honest, I'm completely in the strict camp
Can you explain why? Are you using PHP in a web context? Because everything from the web is a string.
So wouldn't it make the most sense to let the functions using the web data coerce to integer, and just work?
How does putting (int) before the arguments to function help anything?
I actually liked Ze'ev's proposal because it let you be weak while making sure you did not coerce obviously bad data.
Anyway, as a member of the strong camp, can you explain?
Can you explain why? Are you using PHP in a web context? Because everything from the web is a string.
So wouldn't it make the most sense to let the functions using the web data coerce to integer, and just work?
How does putting (int) before the arguments to function help anything?
I actually liked Ze'ev's proposal because it let you be weak while making sure you did not coerce obviously bad data.
Anyway, as a member of the strong camp, can you explain?
> Because everything from the web is a string.
I would start by saying that everything, regardless of domain, is just a stream of bits. Which is completely useless, just like your assertion.
And I know what you meant, but you're also wrong. A JSON object is only a string before being interpreted. An x-www-form-urlencoded is actually a map in which values can be arrays instead of primitives. Such forms often correspond to domain models with a clear definition.
There's also no such thing as "obviously bad data". All data is good in the proper context, therefore automatic conversions that try to make this distinction do not make sense. I don't necessarily know how PHP behaves, but in another popular language there's a world of difference between "077" and "77". There's also a world of difference between integer, floating point and fixed point and the details are never irrelevant.
I would start by saying that everything, regardless of domain, is just a stream of bits. Which is completely useless, just like your assertion.
And I know what you meant, but you're also wrong. A JSON object is only a string before being interpreted. An x-www-form-urlencoded is actually a map in which values can be arrays instead of primitives. Such forms often correspond to domain models with a clear definition.
There's also no such thing as "obviously bad data". All data is good in the proper context, therefore automatic conversions that try to make this distinction do not make sense. I don't necessarily know how PHP behaves, but in another popular language there's a world of difference between "077" and "77". There's also a world of difference between integer, floating point and fixed point and the details are never irrelevant.
> therefore automatic conversions that try to make this distinction do not make sense.
You have to convert it somewhere. I don't see how the caller converting it is any better than the recipient doing it. Having the caller do it seems quite pointless when the recipient is anyway doing it.
Your answer about how everything is bits was quite useless since you completely missed the point. Your input is a string, you have to convert it someplace. Weak mode has the recipient do it. Strict mode you have to do it yourself, and then the recipient double checks.
I see no value in the second option - the actual conversion in both cases is identical.
But Danack disagrees, so I asked him to explain. Your answer was not helpful at all.
You have to convert it somewhere. I don't see how the caller converting it is any better than the recipient doing it. Having the caller do it seems quite pointless when the recipient is anyway doing it.
Your answer about how everything is bits was quite useless since you completely missed the point. Your input is a string, you have to convert it someplace. Weak mode has the recipient do it. Strict mode you have to do it yourself, and then the recipient double checks.
I see no value in the second option - the actual conversion in both cases is identical.
But Danack disagrees, so I asked him to explain. Your answer was not helpful at all.
@ars, you completely missed my point. Lets go over it again. Tell me how should the following things convert:
77
077
77.0I GOT your point. I don't care about your point because it is not the question I am asking.
Why are you answering something I did not ask?
I am asking why does Danack prefer strict mode. There is absolutely nothing in my question that cares about the specific details how you convert bits to types, other than that you do.
My question is entirely about WHO does the conversion. NOT about the conversion itself.
(Oh, and the thing about bad-data has a defined meaning that went over your head because you are not familiar with the debate here. In this context bad-data means data loss on conversion. So "1" to 1 is fine, but "1 a" to 1 is not.)
Why are you answering something I did not ask?
I am asking why does Danack prefer strict mode. There is absolutely nothing in my question that cares about the specific details how you convert bits to types, other than that you do.
My question is entirely about WHO does the conversion. NOT about the conversion itself.
(Oh, and the thing about bad-data has a defined meaning that went over your head because you are not familiar with the debate here. In this context bad-data means data loss on conversion. So "1" to 1 is fine, but "1 a" to 1 is not.)
The conversion itself is very relevant because you cannot establish a default conversion that should happen, therefore the conversions should be explicit, answering the WHO. This is why I asked you about what should the conversion produce in those examples.
And also in the conversion from "1.1" to 1.1 there is loss of information, because the two representations are not isomorphic. Care to guess why?
And also in the conversion from "1.1" to 1.1 there is loss of information, because the two representations are not isomorphic. Care to guess why?
This is the point that ars is making. He is saying that it has to be a runtime check and/or conversion because it is coming over the wire, as a string, at runtime.
So the question he is asking is, if you have to do the check at runtime anyway, what is the benefit of the type hinting? Isn't it just belt and braces?
It seems like a perfectly legitimate question to me.
And by the way, to those downvoters who don't seem to be able to tell the difference between a comment you disagree with and spam, can you please contribute to the conversation by hitting the reply button or alternatively get lost? Only you're ruining it for the rest of us. Thanks
So the question he is asking is, if you have to do the check at runtime anyway, what is the benefit of the type hinting? Isn't it just belt and braces?
It seems like a perfectly legitimate question to me.
And by the way, to those downvoters who don't seem to be able to tell the difference between a comment you disagree with and spam, can you please contribute to the conversation by hitting the reply button or alternatively get lost? Only you're ruining it for the rest of us. Thanks
> Having the caller do it seems quite pointless when the recipient is anyway doing it.
Actually, I disagree. The caller is the only one who has semantic information about what the variable (and hence its value) means. All the callee (recipient) can do is blind cast it. The caller on the other hand can interpret it because it knows the meaning (talking about the developer, not the engine).
Actually, I disagree. The caller is the only one who has semantic information about what the variable (and hence its value) means. All the callee (recipient) can do is blind cast it. The caller on the other hand can interpret it because it knows the meaning (talking about the developer, not the engine).
> Can you explain why?
Over the years, we have refactored our PHP code base to something which is much more bug proof, and a lot of it is because we demand certain types to be passed to types. Currently we use doc types (for which the IDE helps us heaps) and type hinting for objects being passed as arguments.
For a given process (e.g. form submission) there will nevertheless be an entry point where strings from the web are passed in. But if you can minimize that area as much as possible, beyond that one place (a function or class) which understands the mapping from incoming string types to PHP types, you end up with a code base which behaves mostly like a statically type language.
This has reduced a huge subset of bugs which are caused by unexpected input being passed to a function. Having the language itself tell you when you made an error statically while writing is much better than having to wait until runtime.
A similar argument would stand for why we moved from dynamically created strings sent to the database, towards a database abstraction layer where we pick up syntax errors at time of writing.
Over the years, we have refactored our PHP code base to something which is much more bug proof, and a lot of it is because we demand certain types to be passed to types. Currently we use doc types (for which the IDE helps us heaps) and type hinting for objects being passed as arguments.
For a given process (e.g. form submission) there will nevertheless be an entry point where strings from the web are passed in. But if you can minimize that area as much as possible, beyond that one place (a function or class) which understands the mapping from incoming string types to PHP types, you end up with a code base which behaves mostly like a statically type language.
This has reduced a huge subset of bugs which are caused by unexpected input being passed to a function. Having the language itself tell you when you made an error statically while writing is much better than having to wait until runtime.
A similar argument would stand for why we moved from dynamically created strings sent to the database, towards a database abstraction layer where we pick up syntax errors at time of writing.
> Can you explain why?
Hopefully.
> How does putting (int) before the arguments to function help anything?
It wouldn't. Anyone who is casting from an unknown type to an int by using just `(int)` is doing something wrong in my opinion.
Even in web-based applications there are at least two layers of code: i) One where the type of the values are unknown and they are represented as strings. ii) One where the types of the values are known.
At the boundary between these two layers you should have code that inspects the strings that represent the input values, check that they are acceptable, and convert them to the desired type. If the input values cannot be converted to the desired type, the code needs to give an error that is both specific to the type of error so that a computer can understand it, as well as provide a human understandable explanation of why the conversion was not allowed.
The reason why I want strong types is that I never, ever want to blindly cast from one type to another. The decision about how to convert from one type to another, should always be made at a boundary between areas of the application where types are known, and the areas where the types are unknown. I always want to be forced to make that decision in the right place, using code that gives useful errors and messages, rather than having the value coerced into the desired type.
tl;dr I won't use (int) to cast, I will use something like the code below.
cheers Dan
Hopefully.
> How does putting (int) before the arguments to function help anything?
It wouldn't. Anyone who is casting from an unknown type to an int by using just `(int)` is doing something wrong in my opinion.
Even in web-based applications there are at least two layers of code: i) One where the type of the values are unknown and they are represented as strings. ii) One where the types of the values are known.
At the boundary between these two layers you should have code that inspects the strings that represent the input values, check that they are acceptable, and convert them to the desired type. If the input values cannot be converted to the desired type, the code needs to give an error that is both specific to the type of error so that a computer can understand it, as well as provide a human understandable explanation of why the conversion was not allowed.
The reason why I want strong types is that I never, ever want to blindly cast from one type to another. The decision about how to convert from one type to another, should always be made at a boundary between areas of the application where types are known, and the areas where the types are unknown. I always want to be forced to make that decision in the right place, using code that gives useful errors and messages, rather than having the value coerced into the desired type.
tl;dr I won't use (int) to cast, I will use something like the code below.
cheers Dan
function validateOrderAmount($value) : int {
$count = preg_match("/[^0-9]*/", $value);
if ($count) {
throw new InvalidOrderAmount("Order amount must contain only digits.");
}
$value = intval($value);
if ($value < 1) {
throw new InvalidOrderAmount("Order amount must be one or more.");
}
if ($value >= MAX_ORDER_AMOUNT) {
throw new InvalidOrderAmount("You can only order ".MAX_ORDER_AMOUNT." at a time.");
}
return $value;
}
function processOrderRequest() {
$orderAmount = validateOrderAmount($_REQUEST['orderAmount']);
//Yay, our IDE/static code analyzer can tell that $amount is an int if the code reached here.
placeOrder($orderAmount);
}Thank you for the reply! (The rest of the replies to me got seriously derailed....)
So from your code it looks like the only benefit of strict mode is in case you forget to do the validation/conversion it will warn you? I guess that's reasonable. Is there any other benefit?
To me it seems that Ze'ev's proposal would be even better for you - it does the equivalent of the validation and conversion automatically including with an error if it doesn't validate.
You wrote "let's ignore that", but it really seems like to best of all worlds to me. Any idea why it was rejected so badly? Is it because the coercion rules are different from the rest of PHP?
So from your code it looks like the only benefit of strict mode is in case you forget to do the validation/conversion it will warn you? I guess that's reasonable. Is there any other benefit?
To me it seems that Ze'ev's proposal would be even better for you - it does the equivalent of the validation and conversion automatically including with an error if it doesn't validate.
You wrote "let's ignore that", but it really seems like to best of all worlds to me. Any idea why it was rejected so badly? Is it because the coercion rules are different from the rest of PHP?
> Is there any other benefit?
Strict types make it easier to reason about code, that the tl;dr version.
> To me it seems that Ze'ev's proposal would be even better for you - > it does the equivalent of the validation and conversion automatically > including with an error if it doesn't validate.
Rather than having int 'types' which we can reason about, it has int 'values' which are harder to reason about. Types can be reasoned about just by looking at the code. Values can only be reasoned about when running code. A contrived example:
For the coercive scalar type proposal, this code works - except when it doesn't. This code works when $value = 1, 2, 3, 4 and breaks when $value = 5.
This is the fundamental difference; whether conversions between types have to be explicitly done by code, and so any implicit or incorrect conversion can be detected by static code analysis tools, or whether the conversions are done at run time, and so cannot be analyzed fully.
This means most of these errors will be discovered by users on the production servers. Strict mode allows you to eliminate these types of errors.
Yes, this means I need to add a bit of code to do the explicit conversion, but I just don't convert between values that much. Once a value is loaded from a users request, config file or wherever, it is converted once into the type it needs to be. After that, any further change in type is far more likely to be me making a mistake, rather than an actual need to change the type.
> Any idea why it was rejected so badly? Is it because the coercion rules are different from the rest of PHP?
At least in part it was because the RFC was seen as a way to block strict types; about half of the RFC text is shitting on people desires for strict types, which did not make people who want strict types be very receptive. If it had been brought up 6 months ago, there is a good chance it would have passed, or at least would have been closer.
Some parts of the proposal were good - other parts were nuts that were pretty obvious the result of the RFC only being created once the dual mode RFC was announced and about to be put to the vote, with a very high chance of passing.
* Good - "7 dogs" not longer being converted to "7" if someone tries to use it as an int.
* Bad - Different mode for internal function vs userland functions e.g. "Unlike user-land scalar type hints, internal functions will accept nulls as valid scalars." and other small differences. This is even more nuts than you might realise as it means if you extend an internal class, and overload some of the methods on the class, those methods will behave differently to the non-overloaded methods.
* Bad - Subtle and hard to fix BC breaks in conversion which are probably not right anyway. e.g. false -> int # No more conversion from bool true -> string # No more conversion from bool
It is a shame that the discussion became so contentious. It would have been good if the conversion rules could have been tidied up, but all the time and energy had been used up the not particularly productive discussion.
Strict types make it easier to reason about code, that the tl;dr version.
> To me it seems that Ze'ev's proposal would be even better for you - > it does the equivalent of the validation and conversion automatically > including with an error if it doesn't validate.
Rather than having int 'types' which we can reason about, it has int 'values' which are harder to reason about. Types can be reasoned about just by looking at the code. Values can only be reasoned about when running code. A contrived example:
function foo(int $bar){...}
foo(36/$value);
In strict mode, this would be reported as an error by code analysis.For the coercive scalar type proposal, this code works - except when it doesn't. This code works when $value = 1, 2, 3, 4 and breaks when $value = 5.
This is the fundamental difference; whether conversions between types have to be explicitly done by code, and so any implicit or incorrect conversion can be detected by static code analysis tools, or whether the conversions are done at run time, and so cannot be analyzed fully.
This means most of these errors will be discovered by users on the production servers. Strict mode allows you to eliminate these types of errors.
Yes, this means I need to add a bit of code to do the explicit conversion, but I just don't convert between values that much. Once a value is loaded from a users request, config file or wherever, it is converted once into the type it needs to be. After that, any further change in type is far more likely to be me making a mistake, rather than an actual need to change the type.
> Any idea why it was rejected so badly? Is it because the coercion rules are different from the rest of PHP?
At least in part it was because the RFC was seen as a way to block strict types; about half of the RFC text is shitting on people desires for strict types, which did not make people who want strict types be very receptive. If it had been brought up 6 months ago, there is a good chance it would have passed, or at least would have been closer.
Some parts of the proposal were good - other parts were nuts that were pretty obvious the result of the RFC only being created once the dual mode RFC was announced and about to be put to the vote, with a very high chance of passing.
* Good - "7 dogs" not longer being converted to "7" if someone tries to use it as an int.
* Bad - Different mode for internal function vs userland functions e.g. "Unlike user-land scalar type hints, internal functions will accept nulls as valid scalars." and other small differences. This is even more nuts than you might realise as it means if you extend an internal class, and overload some of the methods on the class, those methods will behave differently to the non-overloaded methods.
* Bad - Subtle and hard to fix BC breaks in conversion which are probably not right anyway. e.g. false -> int # No more conversion from bool true -> string # No more conversion from bool
It is a shame that the discussion became so contentious. It would have been good if the conversion rules could have been tidied up, but all the time and energy had been used up the not particularly productive discussion.
> Because everything from the web is a string.
Do you consider JSON a string? Would you manipulate it as a string or use a JSON parser?
> How does putting (int) before the arguments to function help anything?
It throws an error in case you receive bad input, and as we all know you will receive bad input.
Do you consider JSON a string? Would you manipulate it as a string or use a JSON parser?
> How does putting (int) before the arguments to function help anything?
It throws an error in case you receive bad input, and as we all know you will receive bad input.
You get json from the browser?
Of course I manipulate the data - that's exactly what weak mode does, convert the strings into integers. I just don't see how doing the conversion myself manually helps anything.
> It throws an error in case you receive bad input, and as we all know you will receive bad input.
It does no such thing. (int) will simply turn bad input into a zero.
Of course I manipulate the data - that's exactly what weak mode does, convert the strings into integers. I just don't see how doing the conversion myself manually helps anything.
> It throws an error in case you receive bad input, and as we all know you will receive bad input.
It does no such thing. (int) will simply turn bad input into a zero.
> You get json from the browser?
Yes.
Yes.
Really? All the pages you program with forms, and links and whatever are sending you json?
I have no doubt you CAN do it, but most of the time you don't.
And since most of the time you are dealing with strings my question stands: Why do the conversion manually instead of letting the nice new feature do it for you.
I have no doubt you CAN do it, but most of the time you don't.
And since most of the time you are dealing with strings my question stands: Why do the conversion manually instead of letting the nice new feature do it for you.
You've heard of JavaScript I presume?
Even AJAX sites do not typically send all data back as JSON. Most of the time they use normal form-urlencoded data.
If you did send everything as JSON you would be bypassing everything PHP does with form/url data to make things easier for you (for example arrays). That doesn't seem like a good engineering tradeoff.
If you did send everything as JSON you would be bypassing everything PHP does with form/url data to make things easier for you (for example arrays). That doesn't seem like a good engineering tradeoff.
Sending structured data from JavaScript to PHP is much easier via json and in PHP its as easy as calling json_decode() to get back and object or array depending on your preference.
PHP accepts nested key value pairs and frameworks can take advantage of that when accessing the $_REQUEST object. If you're bypassing the functionality that's baked into forms then you're going to have to put it back in at some point or reinvent it yourself.
And then you can't make a request to the server directly unless you format your data as JSON, which is a bit inconvenient, especially if you're debugging a problem.
So if using JSON as a container isn't gaining you some other benefit then it's probably best avoided.
And then you can't make a request to the server directly unless you format your data as JSON, which is a bit inconvenient, especially if you're debugging a problem.
So if using JSON as a container isn't gaining you some other benefit then it's probably best avoided.
If you live in one framework and always will, then I see your point. But if you want to have the ability to code out native solutions, use other tools where other tools may be more appropriate, or discipline your projects to be a little less biased, then asking PHP to parse JSON is not a huge buy.
That's how we've done it here and the modularization it has provided us has been incredible. PHP's json_encode and json_decode are also quite fast.
That's how we've done it here and the modularization it has provided us has been incredible. PHP's json_encode and json_decode are also quite fast.
I don't really get your reasoning there. Forms are the mechanism for making parameterised requests over HTTP. If REST is your platform then it makes sense to start with them, regardless of any framework you are using.
I'm not saying using JSON as an envelope won't work - it is clearly working for you - just that I wouldn't start there, and I can't see that you couldn't work with the request object directly.
I'm not saying using JSON as an envelope won't work - it is clearly working for you - just that I wouldn't start there, and I can't see that you couldn't work with the request object directly.
What happened to PHP6?
It was partly voted to skip the number 6 due to the numerous books available for sale that covered the original PHP 6 draft. This would cause confusion for people attempting to learn the new specification.
Examples on Amazon: http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3D...
The vote: https://wiki.php.net/rfc/php6
Examples on Amazon: http://www.amazon.com/s/ref=nb_sb_noss_1?url=search-alias%3D...
The vote: https://wiki.php.net/rfc/php6
From the voting page:
> The decimal system (or more accurately the infinite supply of numbers we have) makes it easy for us to skip a version, with plenty more left for future versions to come.
Hard to argue with that!
> The decimal system (or more accurately the infinite supply of numbers we have) makes it easy for us to skip a version, with plenty more left for future versions to come.
Hard to argue with that!
PHP6 was supposed to be this all-singing all-dancing Unicode support release. It dragged on for years but didn't get finished due to various issues, and in 2008 they decided to just scrap it and roll what they could salvage into 5.3
Since PHP6 died, it made sense to avoid confusion and not name the new major version 6, since we'd then have two different PHP 6es.
This is not unlike what happened with ECMAScript 4.
Since PHP6 died, it made sense to avoid confusion and not name the new major version 6, since we'd then have two different PHP 6es.
This is not unlike what happened with ECMAScript 4.
That's funny; I used nearly the exact same phrasing to describe PHP 6 a few months ago:
https://www.reddit.com/comments/2qyuhc/new_rfc_for_scalar_ty...
https://www.reddit.com/comments/2qyuhc/new_rfc_for_scalar_ty...
Ah, I may have subconsciously copied the way you said it, I think I've read your comment before. Sorry about that!
That's what should have happened with Perl a decade ago.
Eloped with Windows 9.
It got a call from ECMAScript 4.
most of it was rolled into 5.4. i think some of the more contentious unicode parts were dropped.
Finally! I had a lot of concerns about this, but I think they're mostly answered by the discussion. I do like the way union types work (at least nullable types) in Hack, but I think they existing `foo(int $param = null)` approach is fine for 99% of cases, and those that it doesn't work for can go back to type-checking at the top of the function (ie do what we have to do for all scalar types right now).
While I understand the optional strict mode, I do find it quite confusing: it looks similar to javascript's 'use strict';, and at first glance it sounds like it should be similar to `error_reporting(E_STRICT)`, yet somehow scoped to the <?php ?>. Personally I like the `strict namespace` approach they proposed the most. The argument against is that it will read like everything in that namespace is strict, when it's actually limited to the file, but I think it's pretty clear if I read in a.php `strict namespace Qaribou;` and in b.php `namespace Qaribou;`, that a.php is strict and b.php is not. I really don't see the ambiguity there.
While I understand the optional strict mode, I do find it quite confusing: it looks similar to javascript's 'use strict';, and at first glance it sounds like it should be similar to `error_reporting(E_STRICT)`, yet somehow scoped to the <?php ?>. Personally I like the `strict namespace` approach they proposed the most. The argument against is that it will read like everything in that namespace is strict, when it's actually limited to the file, but I think it's pretty clear if I read in a.php `strict namespace Qaribou;` and in b.php `namespace Qaribou;`, that a.php is strict and b.php is not. I really don't see the ambiguity there.
speaking of phpng, it now scores 1s better on the wordpress unit tests than just 3 month ago: https://wiki.php.net/phpng
Hooray! \o/
I haven't had a use for this yet, but I'm always amazed by how PHP manages to move forward without breaking BC.
I haven't had a use for this yet, but I'm always amazed by how PHP manages to move forward without breaking BC.
You've had a use for this ever since you started writing code. You just haven't realized it yet.
Since I can't see the forest from the trees here, care to provide an example or two?
I've had cases where I want to only allow certain values (most often int) into certain functions (usually __construct, when looking at a primary key in a database), but in these cases I prefer to cast values. (int)$foo hasn't failed me yet, and I've internalized it as much as I've internalized running application output through htmlentities.
I can see this being extremely useful if you plan on using PHP as a general purpose language, but I never have. I'd rather jump to Java/C++/Rust if I had to do numeric calculations (things like images, real time calculations, etc.)
I've had cases where I want to only allow certain values (most often int) into certain functions (usually __construct, when looking at a primary key in a database), but in these cases I prefer to cast values. (int)$foo hasn't failed me yet, and I've internalized it as much as I've internalized running application output through htmlentities.
I can see this being extremely useful if you plan on using PHP as a general purpose language, but I never have. I'd rather jump to Java/C++/Rust if I had to do numeric calculations (things like images, real time calculations, etc.)
Let's say the constructor you mentioned is for an ORM. Let's also say you're using a database library or PHP extension that you're not 100% familiar with, or maybe it just has a bug in a new version that you just updated to.
You pull out a particular row from this library/extension, and it contains an empty string (or even null) as the value for the primary key field.
Using typecasting, you'd get a value of 0, which is wrong. It would fail silently, and you'd only discover the error when you realize you're working on a row with no data. You'd even be able to update the row silently, because "UPDATE whatever SET x = y WHERE id = 0" is valid SQL!
With primitive type hints, you'd know immediately that you're getting an empty value from your DB, and you could go straight to fixing that instead.
In the past, people have had to write a bunch of unit tests to avoid all these issues. With primitive type hints, you could just type the word "int" and be done with it.
All that said, I still say all the people that are excited about this are much better off switching to a strictly-typed language, because my example above is just the tip of the iceberg when it comes to juggling types.
You pull out a particular row from this library/extension, and it contains an empty string (or even null) as the value for the primary key field.
Using typecasting, you'd get a value of 0, which is wrong. It would fail silently, and you'd only discover the error when you realize you're working on a row with no data. You'd even be able to update the row silently, because "UPDATE whatever SET x = y WHERE id = 0" is valid SQL!
With primitive type hints, you'd know immediately that you're getting an empty value from your DB, and you could go straight to fixing that instead.
In the past, people have had to write a bunch of unit tests to avoid all these issues. With primitive type hints, you could just type the word "int" and be done with it.
All that said, I still say all the people that are excited about this are much better off switching to a strictly-typed language, because my example above is just the tip of the iceberg when it comes to juggling types.
I take your point that this is nice syntactic sugar, but I don't like your example. You wouldn't typecast in this situation. You would check the value with is_numeric() or similar.
They're pretty inconsistent about it. They tend to avoid large deliberate breaks, but you still see smaller incompatibilities.
Off the top of my head, here's a case where they changed the output of a hash function between 5.3 and 5.4, breaking it for all previous users. https://bugs.php.net/bug.php?id=60221
Off the top of my head, here's a case where they changed the output of a hash function between 5.3 and 5.4, breaking it for all previous users. https://bugs.php.net/bug.php?id=60221
The only consistent thing about PHP is its inconsistency ;)
Well, at least you know what you're getting into. It's not like they promise otherwise anywhere.
Well, at least you know what you're getting into. It's not like they promise otherwise anywhere.
> I haven't had a use for this yet, but I'm always amazed by how PHP manages to move forward without breaking BC.
This. If I were a Python developer (of the language itself), I would be paying very close attention to how PHP has handled deprecation and breaking changes.
This. If I were a Python developer (of the language itself), I would be paying very close attention to how PHP has handled deprecation and breaking changes.
Really? I see it as the exact opposite. Sure, Python added some pain from 2-3. They did so to fix the main flaws in the language and remove deprecated stuff. The language is now far better and the cost has mostly been paid. The alternative is the PHP approach where everything hangs around for ever, and everyone is using deprecated stuff, everything is named weirdly and lots of extra gunk has to be shoved in to try and make it work in a sane way because "we didn't want to break anything".
I understand why some people prefer that, and why it's the way most languages go (Java does the same thing, just with way less movement in general compared to PHP), but it means that the language gets worse over time. Eventually, if you don't do that breaking change, the language will get replaced by something that doesn't need all the cludge.
I understand why some people prefer that, and why it's the way most languages go (Java does the same thing, just with way less movement in general compared to PHP), but it means that the language gets worse over time. Eventually, if you don't do that breaking change, the language will get replaced by something that doesn't need all the cludge.
There's been an effort with PHP 7 to try and avoid a Python 2/3-style situation. The PHP 5 to 7 jump should be much smaller than from 4 to 5.
>The PHP 5 to 7 jump should be much smaller than from 4 to 5.
And also the jump from 5.4+ to 7 is probably smaller than the jump from 5.2 to 5.3.
Although I think the PHP project does need to support versions for longer, the adoption rate of 7 is going to be quite rapid due to the low barrier of doing it, and the massive performance and language gains.
And also the jump from 5.4+ to 7 is probably smaller than the jump from 5.2 to 5.3.
Although I think the PHP project does need to support versions for longer, the adoption rate of 7 is going to be quite rapid due to the low barrier of doing it, and the massive performance and language gains.
Python 2 -> 3 did not have the luxury that PHP did with 4 -> 5. Python still worked, whereas PHP 4 was running around with its hair on fire screaming for a fire extinguisher that was PHP 5.
Bad analogy, but the point is that Python still worked for most people so the upgrade process was slow.
I think Go is going to have issues similar to Python when they make the jump to 2.0. The devs are already on record saying that BC will break.
Bad analogy, but the point is that Python still worked for most people so the upgrade process was slow.
I think Go is going to have issues similar to Python when they make the jump to 2.0. The devs are already on record saying that BC will break.
I love PHP.
I think of it as the English language of programming. Picking and choosing all of the best bits from every other language, and bastardizing them into it's own everyday use.
I think of it as the English language of programming. Picking and choosing all of the best bits from every other language, and bastardizing them into it's own everyday use.
Have you heard of https://en.wikipedia.org/wiki/Stockholm_syndrome?
Have you heard of https://en.wikipedia.org/wiki/Poe's_law?
It's very clearly not sarcasm.
If I cut off the limbs of a bunch of athletes and glue them together, it doesn't make a better athlete.
I hope you don't find analogies like that. It doesn't make sense to compare athletes to programming languages; that analogy makes no sense at all.
Also +1 to what @Padding says.
Also +1 to what @Padding says.
It's obviously not a precise analogy :)
However, it gets the point across; taking a bunch of bits from disparate well-functioning systems and smashing them together doesn't guarantee that you'll get another well-functioning system.
However, it gets the point across; taking a bunch of bits from disparate well-functioning systems and smashing them together doesn't guarantee that you'll get another well-functioning system.
Do you like Go? Part of the process for creating Go was to take the best parts of other languages and glue them together, while also throwing out as many features as possible.
Funny you should ask :) I'm best known for my article criticizing Go's design. I think Go is a reactionary language; it says "To hell with the last 30 years of language research; we want the good old K&R days back!" while making a few token admissions to progress (like good green threading). In reality, this approach eliminated everything that made C elegant (C is universally compatible with basically all Von Neumann computers, and Go certainly isn't) without actually taking advantage of 99% of the progress we've made. I'd hardly say Go has many of the "best parts" of other languages.
Depends on the sport.
Maybe that's because gluing together limbs is still an open research issue while gluing together ideas is merely a mental excercise?
I think the part where you said "best bits" is debatable.
I too love PHP!
Can somebody explain this to a non-phper? So PHP got strict types, but only for Scalars (Ints and floats) and they can be enabled on a per-file basis. Right?
PHP has had type hints for classes for more than a decade now:
Since PHP has a long tradition of weak typing and this is what PHP's built-in and extension functions use, weak is the default behaviour, allowing some conversions:
function foobar(MyClass $foo) {
// do stuff
}
foobar(new NotMyClass()); // throws an error
This just adds type hints for the scalar types (integer, float, string and boolean).Since PHP has a long tradition of weak typing and this is what PHP's built-in and extension functions use, weak is the default behaviour, allowing some conversions:
function foo(int $x) {
var_dump($x);
}
foo("12"); // produces int(12)
foo(null); // throws an error
But, you can optionally turn on a strict type-checking mode for scalars on a per-file basis, which doesn't allow conversions: <?php
declare(strict_types=1);
function foo(int $x) {
var_dump($x);
}
foo("12"); // throws an error
foo(null); // throws an errorPHP has had type-hints for parameters for several version, but they could only be used for classes. The new types-hints cover the 'scalar' values (aka not object) and are int, float, string and bool. They allow a function to declare what they types of the variables it receives should be like:
function foo(int $x) { // x is guaranteed to be an int. }
The type-hinting for scalars has two modes:
* strict - the parameter passed to the function must be of the exact* type. * weak - the parameter passed to the function will be converted to the correct type.
The strictness depends on what mode PHP was in when the function was called. This is the right choice as it:
* Allows library authors to write their code in either strict or weak mode.
* End-users to write their code in either strict or weak mode. Or even without using scalar type-hints.
* End-user to be able to choose when they are writing their code do they want their variables to be converted to the type expected by the library automatically, or do they want PHP to give them an error if they accidentally pass the wrong type of variable to a function that is expecting an int.
*except for some widening rules, e.g. you can pass an int where a float is expected, as ints can be converted into float without data loss (for ints less than 2^53).
function foo(int $x) { // x is guaranteed to be an int. }
The type-hinting for scalars has two modes:
* strict - the parameter passed to the function must be of the exact* type. * weak - the parameter passed to the function will be converted to the correct type.
The strictness depends on what mode PHP was in when the function was called. This is the right choice as it:
* Allows library authors to write their code in either strict or weak mode.
* End-users to write their code in either strict or weak mode. Or even without using scalar type-hints.
* End-user to be able to choose when they are writing their code do they want their variables to be converted to the type expected by the library automatically, or do they want PHP to give them an error if they accidentally pass the wrong type of variable to a function that is expecting an int.
*except for some widening rules, e.g. you can pass an int where a float is expected, as ints can be converted into float without data loss (for ints less than 2^53).
they could have been interfaces, or arrays too.
[deleted]
Yay! <3 PHP.
Also, the moment I read declare(strict_types..., for some reason "use strict"; from ECMAScript flashed in front of me :D
Also, the moment I read declare(strict_types..., for some reason "use strict"; from ECMAScript flashed in front of me :D
We looked into using it. After much thought, we decided not to, here's why: https://wiki.php.net/rfc/scalar_type_hints_v5#why_not_use_us...
I break down all of the proposed alternatives and the cases against them.
I break down all of the proposed alternatives and the cases against them.
Same idea, except `use \Foo\Bar\Baz as SomeAlias` is already reserved for namespaces.
Also, we already have use strict; as an easter egg ;)
Exactly how do you trigger the easter egg, and what does it do?
$ php -a
php > use strict;
PHP Fatal error: You seem to be trying to use a different language... in php shell code on line 1
php > use strict;
PHP Fatal error: You seem to be trying to use a different language... in php shell code on line 1
Thanks. I had tried it in 5.3 and only got the boring "The use statement with non-compound name 'strict' has no effect" error: http://3v4l.org/WY1Vs
Okay, I have to admit, that is pretty amusing. :)
That made my day, thanks
Oh my! That deserves another HN post in itself! <3
If you say so! https://news.ycombinator.com/item?id=9219372
[deleted]
"use strict";
(note 'use' is part of a string) should work in PHP for the same reason it does in ECMAScript -- it is a no-op at the language level (creating a string literal and doing nothing with it), that is unlikely to appear in old code, and can be given new meaning in the next-level language spec.Maybe. But it means the parser now needs to "make sense" of strings whereas before it was just skipping over them.
No it doesn't. The "use strict" declaration must occur before any other statements, allowing the parser to look specifically for those bytes, and treat it as a separate token instead of as a string. It doesn't have to inspect the contents of all strings.
Good. Now I just need to wait for PHPStorm to support them ;)
Submit a feature request! ;)
I can't find it anywhere in the document - are these statically checked types or just run time checks (contracts)?
Runtime (like PHP's existing type hints), but they could be checked statically by IDEs and such. One benefit of strict mode is that it enables much better static checking than weak mode, because validity is determined by type and never value.
Wow, interesting:
"Whether or not the function being called was declared in a file that uses strict or weak type checking is irrelevant. The type checking mode depends on the file where the function is called."
That means that my function can have a parameter defined as an int in its strict file, but if it's called from outside of it, anything can still be passed to that parameter, right?
I'm not sure how I like that. What if you're passing input from class A into class BStrict then using BStrict to call a function in CStrict? BStrict and CStrict are defined as strict, where A is not. Would BStrict then be the one throwing the error because the "caller" is the issue?
From the description it seems that the parameters are effectively ignored in BStrict when A calls it.
Am I missing something or does this sound iffy?
Edit: Link for quote - https://wiki.php.net/rfc/scalar_type_hints_v5#parameter_type...
"Whether or not the function being called was declared in a file that uses strict or weak type checking is irrelevant. The type checking mode depends on the file where the function is called."
That means that my function can have a parameter defined as an int in its strict file, but if it's called from outside of it, anything can still be passed to that parameter, right?
I'm not sure how I like that. What if you're passing input from class A into class BStrict then using BStrict to call a function in CStrict? BStrict and CStrict are defined as strict, where A is not. Would BStrict then be the one throwing the error because the "caller" is the issue?
From the description it seems that the parameters are effectively ignored in BStrict when A calls it.
Am I missing something or does this sound iffy?
Edit: Link for quote - https://wiki.php.net/rfc/scalar_type_hints_v5#parameter_type...
> That means that my function can have a parameter defined as an int in its strict file, but if it's called from outside of it, anything can still be passed to that parameter, right?
Not at all. It's "weak" typing, not no typing.
A small set of convertible values can be passed and will be converted to the type you asked for, while other values error as usual.
See the rest of the RFC.
Not at all. It's "weak" typing, not no typing.
A small set of convertible values can be passed and will be converted to the type you asked for, while other values error as usual.
See the rest of the RFC.
You're right, I see that now. That's why they went into describing type conversions too. Thanks for the insight!
Sounds right to me. If you're using untyped code, you shouldn't care what you're calling into. strict mode should only apply when both parties agree to it, otherwise strict mode would be the default and you'd have to explicitly mark code as unstrict.
That's right, the PHP community _votes_ on language features.
Since PHP has switched to community voting, the language has expanded smartly by leaps and bounds while maintaining a great degree of compatibility.
Though there is a lot of controversy about who is allowed to vote. Currently it's anyone with a php.net account, which is:
* People who have commit access to git/svn
* Documentation contributors
* Documentation translators
* PEAR package maintainers
* PECL package maintainers
* Very few "community representatives"
* People who have commit access to git/svn
* Documentation contributors
* Documentation translators
* PEAR package maintainers
* PECL package maintainers
* Very few "community representatives"
While I won't go even close to the PHP internals list, deciding on the community representatives will be... interesting. Drupal, which http://w3techs.com/technologies/details/cm-drupal/all/all powers 2% of the web has an army of subsystem http://cgit.drupalcode.org/drupal/tree/core/MAINTAINERS.txt maintainers. If you open the gates, whom of them will be allowed to and who won't? Fascinating.
Generally the idea is to give the head of the project a vote.
Agreed. I think I still have a vote, and I haven't been involved in PHP for about 6 years.
Is this compatible with what Facebook has done with Hack?
There's no fundamental incompatibility. Hack files don't use <?php tags, they use <?hh tags. I'm sure Facebook will make HHVM handle PHP type declarations alongside Hack type declarations, though exactly how they'll interact remains to be seen.
This is going to depend on how Facebook decides to maintain their PHP spec. They might decide to fork it for all we know.
But honestly, if you're using HHVM already, you should have as much tooling/documentation as you need to switch to Hack itself within the next year or so, so all this PHP discussion is moot.
But honestly, if you're using HHVM already, you should have as much tooling/documentation as you need to switch to Hack itself within the next year or so, so all this PHP discussion is moot.
(imho, not only good, but awesome stuff, like XHP https://www.facebook.com/notes/facebook-engineering/xhp-a-ne... and async/await http://docs.hhvm.com/manual/en/hack.async.php)
And as a bonus, both HHVM.PHP and Hack and are well optimized to run at Facebook's scale... seriously, let's just leave Zend.PHP rot away in the trashcan of history and move the f on!