Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/
Hi Andrea
-----Ursprüngliche Nachricht-----
Von: Andrea Faulds [mailto:ajf@ajf.me]
Gesendet: Mittwoch, 14. Januar 2015 01:17
An: PHP Internals List
Betreff: [PHP-DEV] [RFC] Scalar Type Hints v0.2Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the
updated RFC from the v0.1 RFC.Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/--
I had a few thoughts on the new proposed declare(strict_typehints=TRUE); construct and I must say I do not really like that we would have different behaviour just based on a directive. This is quite ugly from a readability point of view since I as user cannot easily see whether somewhere (above) in the code the directive was set (I have changed my mind a little bit below - left it here for traceability purposes). Which brings me to the question what happens with the following code:
function foo(int $a){} //is weak right?
declare(strict_typehinting=TRUE);
I guess it is weak since you wrote: "If this boolean value is TRUE, strict type-checking mode is used for function calls in the remainder of the file"
Maybe it is a good idea to add such an example to the examples as well.
Now, having rethought my own email, I think we should enforce some code style to avoid a huge mess. Why not declare that the directive needs to be the very first statement inside a namespace scope (unless the directive block syntax is used). This way it would be easily verifiable for the user if strict mode is in place or not. But then again, we could also argue that is up to code conventions/code guidelines and they should specify whether mixing both modes is ok and where the directive has to be placed. So re-rethinking what I just wrote I would say it is fine as it is now but we should at least consider if we want to enforce some code practice to avoid a mess.
Now another point: "Whether or not the function being called was declared in a file that uses strict or weak type checking is entirely irrelevant. The type checking mode depends on the file where the function is called."
Seems quite strange to me but fair enough, why not -- actually makes perfectly sense for this RFC -> leaving it to the user to decide what he/she likes :-)
Hey Robert,
I had a few thoughts on the new proposed declare(strict_typehints=TRUE); construct and I must say I do not really like that we would have different behaviour just based on a directive. This is quite ugly from a readability point of view since I as user cannot easily see whether somewhere (above) in the code the directive was set (I have changed my mind a little bit below - left it here for traceability purposes). Which brings me to the question what happens with the following code:
function foo(int $a){} //is weak right?
declare(strict_typehinting=TRUE);I guess it is weak since you wrote: "If this boolean value is TRUE, strict type-checking mode is used for function calls in the remainder of the file"
Maybe it is a good idea to add such an example to the examples as well.
Yes, it only affects stuff which comes after it. But in the example you just gave it doesn’t do anything, because the type checking mode is about the caller (where the function is called), not the callee (where the function is defined).
A better example:
<?php
foo(1.0); // weak
declare(strict_typehints=TRUE);
foo(1); // strict
Now, having rethought my own email, I think we should enforce some code style to avoid a huge mess. Why not declare that the directive needs to be the very first statement inside a namespace scope (unless the directive block syntax is used). This way it would be easily verifiable for the user if strict mode is in place or not. But then again, we could also argue that is up to code conventions/code guidelines and they should specify whether mixing both modes is ok and where the directive has to be placed. So re-rethinking what I just wrote I would say it is fine as it is now but we should at least consider if we want to enforce some code practice to avoid a mess.
We could possible require it to be at the top of the file, maybe. Though I expect people will probably do this anyway. I’m sure it’ll become part of PSR-whatever and there’ll be some sort of standard.
By the way, you can mark some blocks as having different behaviour, e.g.:
<?php
declare(strict_typehints=TRUE) {
foo(1);
}
declare(strict_typehints=FALSE) {
bar(2);
}
This way, it’s more obvious that they have different behaviour.
Now another point: "Whether or not the function being called was declared in a file that uses strict or weak type checking is entirely irrelevant. The type checking mode depends on the file where the function is called."
Seems quite strange to me but fair enough, why not -- actually makes perfectly sense for this RFC -> leaving it to the user to decide what he/she likes :-)
That’s the idea. I didn’t like the idea of having an API force you to deal with a particular approach, especially since it’d mean some of your calls would be strict, others weak. This way it’s completely consistent: everything is strict, or everything is weak, and you get to choose. :)
Thanks for your comments.
Andrea Faulds
http://ajf.me/
Andrea,
With all the respect this RFC is way worst than the v0.1:
We still have a BC break but now we also have code with mutant behavior
that might become buggy (do unexpected things) if a declare
is used. As a
language user and a package maintainer it would be a huge problem. Imagine
how would be to maintain a package that can be used with both strict and
coercive type checking. We would have to write 2x more tests and yet
pollute code with manual type checks (is_string, is_integer) for the non
strict runtime mode when type check is necessary.
This RFC is a huge regression, IMMO, -1 here
2015-01-14 5:22 GMT-03:00 Robert Stoll php@tutteli.ch:
Hi Andrea
-----Ursprüngliche Nachricht-----
Von: Andrea Faulds [mailto:ajf@ajf.me]
Gesendet: Mittwoch, 14. Januar 2015 01:17
An: PHP Internals List
Betreff: [PHP-DEV] [RFC] Scalar Type Hints v0.2Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC,
and bumped its version to 0.2.Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the
RFC, so it’d be sensible to separate discussion of the
updated RFC from the v0.1 RFC.Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/--
To unsubscribe,
visit: http://www.php.net/unsub.phpI had a few thoughts on the new proposed declare(strict_typehints=TRUE);
construct and I must say I do not really like that we would have different
behaviour just based on a directive. This is quite ugly from a readability
point of view since I as user cannot easily see whether somewhere (above)
in the code the directive was set (I have changed my mind a little bit
below - left it here for traceability purposes). Which brings me to the
question what happens with the following code:function foo(int $a){} //is weak right?
declare(strict_typehinting=TRUE);I guess it is weak since you wrote: "If this boolean value is TRUE, strict
type-checking mode is used for function calls in the remainder of the file"
Maybe it is a good idea to add such an example to the examples as well.Now, having rethought my own email, I think we should enforce some code
style to avoid a huge mess. Why not declare that the directive needs to be
the very first statement inside a namespace scope (unless the directive
block syntax is used). This way it would be easily verifiable for the user
if strict mode is in place or not. But then again, we could also argue that
is up to code conventions/code guidelines and they should specify whether
mixing both modes is ok and where the directive has to be placed. So
re-rethinking what I just wrote I would say it is fine as it is now but we
should at least consider if we want to enforce some code practice to avoid
a mess.Now another point: "Whether or not the function being called was declared
in a file that uses strict or weak type checking is entirely irrelevant.
The type checking mode depends on the file where the function is called."
Seems quite strange to me but fair enough, why not -- actually makes
perfectly sense for this RFC -> leaving it to the user to decide what
he/she likes :-)
Hi Marcio,
We still have a BC break but now we also have code with mutant behavior that might become buggy (do unexpected things) if a
declare
is used. As a language user and a package maintainer it would be a huge problem. Imagine how would be to maintain a package that can be used with both strict and coercive type checking. We would have to write 2x more tests and yet pollute code with manual type checks (is_string, is_integer) for the non strict runtime mode when type check is necessary.
I don’t see why this would create “mutant” or “buggy” behaviour. You always get the type you ask for: the weak behaviour is precisely the same as in v0.1. The strict behaviour is fairly intuitive. In no case will you ever receive the wrong type.
I don’t understand.
Andrea Faulds
http://ajf.me/
On
15
Jan
2015,
at
0:33, Andrea Faulds ajf@ajf.me:
Hi Marcio,
We still have a BC break but now we also have code with mutant
behavior that might become buggy (do unexpected things) if adeclare
is
used. As a language user and a package maintainer it would be a huge
problem. Imagine how would be to maintain a package that can be used with
both strict and coercive type checking. We would have to write 2x more
tests and yet pollute code with manual type checks (is_string, is_integer)
for the non strict runtime mode when type check is necessary.
I don’t see why this would create “mutant” or “buggy” behaviour. You always
get the type you ask for: the weak behaviour is precisely the same as in
v0.1. The strict behaviour is fairly intuitive. In no case will you ever
receive the wrong type.
I don’t understand.
Andrea Fauld
s
Hello Andrea!
Consider what a mess was register_globals and problems it had, but at least
it was a global setting. Declare will work on per file basis, and it will
end up even more of a mess.
I think PHP development community learned that lesson and that's why you
get pushback, and not only from internals, but also from the userland. Me
including.
Rergards,
Arvids.
On Thu, 15 Jan 2015 14:30:48 +0300, Arvids Godjuks
arvids.godjuks@gmail.com wrote:
Hello Andrea!
Consider what a mess was register_globals and problems it had, but at
least
it was a global setting. Declare will work on per file basis, and it will
end up even more of a mess.I think PHP development community learned that lesson and that's why you
get pushback, and not only from internals, but also from the userland. Me
including.
What does it have with register_globals in common? Why would it be a mess?
Consider what a mess was register_globals and problems it had, but at
least
it was a global setting. Declare will work on per file basis, and it will
end up even more of a mess.I think PHP development community learned that lesson and that's why you
get pushback, and not only from internals, but also from the userland. Me
including.What does it have with register_globals in common? Why would it be a mess?
Removing 'register_globals' breaks code for users who have no idea that
their sites are even using it. deprecating on one version - which one is
told to switch off the warnings for - just means that when the hosting
skips a version the site simply stops working. That is why 5.2 is still
around and why hosting companies have problems ... and I still have code
which relies on 'register_globals' today because those sites are simply
working. There is simply no time to 'fix' them :(
At the end of the day the whole of the legacy codebase either has to be
brought forward, or PHP5 will be hanging around for some of the same
reasons PHP4 did. Bringing in more areas where differences between code
bases can diverge again over time is creating the same black holes in
the future.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Consider what a mess was register_globals and problems it had, but at
least
it was a global setting. Declare will work on per file basis, and it
will
end up even more of a mess.I think PHP development community learned that lesson and that's why you
get pushback, and not only from internals, but also from the userland.
Me
including.What does it have with register_globals in common? Why would it be a
mess?Removing 'register_globals' breaks code for users who have no idea that
their sites are even using it. deprecating on one version - which one is
told to switch off the warnings for - just means that when the hosting
skips a version the site simply stops working. That is why 5.2 is still
around and why hosting companies have problems ... and I still have code
which relies on 'register_globals' today because those sites are simply
working. There is simply no time to 'fix' them :(At the end of the day the whole of the legacy codebase either has to be
brought forward, or PHP5 will be hanging around for some of the same
reasons PHP4 did. Bringing in more areas where differences between code
bases can diverge again over time is creating the same black holes in
the future.
You keep bringing this up, but there is a workaround to manually "enable"
register globals again if you need to have it for migration. It should just
work (TM) (haven't actually used it)
foreach ($_REQUEST as $k => $v) { $GLOBALS[$k] = $v; }
Not sure why we have to discuss this over and over again on this list.
--
Lester Caine - G8HFLContact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
You keep bringing this up, but there is a workaround to manually "enable"
On PHP5.4 or later? We are stuck with 5.3 unless code is modified. Same
with other removed functions in 5.4.
register globals again if you need to have it for migration. It should just
work (TM) (haven't actually used it)foreach ($_REQUEST as $k => $v) { $GLOBALS[$k] = $v; }
Not sure why we have to discuss this over and over again on this list.
Yes there are work arounds which once one knows that is why a site has
failed can be applied, but it is one of the reasons PHP5.2/3 is still
remaining on shared hosting. No body has the time to hand hold their
customers through the changes.
The CORRECT fix is to work out why it is needed, and properly sort out
the code, as with so many of the breaks brought into PHP5. It is still a
brick wall that users have to scale, so in the context of current
discussions can we possibly avoid adding more of them with PHP7 which is
I am sure why Arvids brough it up.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.
Also, there's this, that you might be able to re-purpose.
https://github.com/php/php-src/blob/d5dd29/Zend/zend_compile.c#L7199
Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.
I don’t like the idea of being forced to use strict (or weak) type checking because the API author decided as much.
More importantly, having the function and not its caller decide makes the addition of type hints to existing code difficult, because it will (possibly unintentionally) rely on PHP’s weak typing and thus error when faced with a strict type check. On the other hand, having the callee decide means that you can relatively safely add type hints to existing code and its consumers will not error. You can then gradually migrate that consuming code over to strict type-checking, if you so wish.
Also, there's this, that you might be able to re-purpose.
https://github.com/php/php-src/blob/d5dd29/Zend/zend_compile.c#L7199
I don’t want to get rid of that easter egg, and I prefer the declare() syntax since it’s more obviously some sort of directive (use strict; looks like an innocuous use statement) and supports the block syntax.
--
Andrea Faulds
http://ajf.me/
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Wednesday, January 14, 2015 11:33 AM
To: Leigh
Cc: PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.I don’t like the idea of being forced to use strict (or weak) type
checking
because the API author decided as much.
I don't either. But I don't like the user to do it either, it's something
that is a part of the language definition.
I completely agree with both Robert and Leigh. I liked the v0.1 one, but
v0.2 is DOA from my point of view. Arguably, from my POV, it's the one
option that's even worse than having strict typing exclusively.
Zeev
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Wednesday, January 14, 2015 11:33 AM
To: Leigh
Cc: PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.I don’t like the idea of being forced to use strict (or weak) type
checking
because the API author decided as much.I don't either. But I don't like the user to do it either, it's something
that is a part of the language definition.I completely agree with both Robert and Leigh. I liked the v0.1 one, but
v0.2 is DOA from my point of view. Arguably, from my POV, it's the one
option that's even worse than having strict typing exclusively.Zeev
The issue of scalar type hinting has been around for a while, with various
proposals and RFCs, but no consensus. Each time a certain level of progress
is made, more issues arise.
It would seem that the major issues is that whatever a library/framework
developer decides, the user of that library/framework would have to develop
their application to fit. Is this such a bad thing? The comeback to that is
that PHP supports type juggling, so there is a different mechanism for
non-scalars to scalars. Fair enough.
From the lib developer's perspective, if a parameter to a function/method
is going to be treated as an integer and is expected to be an integer, then
they should be able to force/limit this just like they can when they say it
must be an array/callable/class/interface. But take into account the option
to enforce the type juggling.
I get 3 questions from this.
1 - Should the type hint restrict non matching types?
2 - When should the value be juggled to match the type hint if it is
different?
3 - Could we allow different signatures for the same method name? - A
different question entirely, but one that may be worth having in relation
to this proposal.
Whatever mechanism is used, it needs to be of zero effort for the user, but
fully understood of the effect.
I think to answer all of this, and to provide enough flexibility that
everyone can be made happy and understand the effect, I think the issues
could be resolved with the following.
1 - A type hint of 'scalar' is required.
This excludes other types (array/callable/class/interface) and would
specifically mean that no type juggling will take place as part of the
parameter passing.
If no type juggling is going to take place, why does it matter what the
type hint is? The advantage of having 'scalar' as a type hint is, as I
said, excludes non-scalars.
Now, if the method does something to the value and the value is passed by
reference, then that would need to be documented clearly.
2 - A scalar type type hint will automatically juggle. PHP is a dynamic
language and, as such, type juggling is used throughout. It shouldn't be
any different when a parameter is type hinted for scalars.
The frustration seems to be that without a way to say that this scalar will
NOT be type juggled (loose) or that it will be (strong) then we cannot move
forward.
Now, some of the comments related to this proposal (and others) is what to
do when the scalar type is of a different type to the parameter.
I think I've covered this by the use of the type hint 'scalar'.
Scalars get type juggled. Period. For good or bad. Until PHP becomes a
strongly type language, type juggling exists.
With the hinting, we can let users know that type juggling will now also
apply to parameters.
So.
<?php
// Any type.
function anyType($a){}
// Current types.
function anArray(array $b){}
function aCallable(callable $c){}
function aClass(stdclass $d){}
function anInterface(Countable $e){}
// Any scalar - not juggled.
function anyScalar(scalar $f){}
// Any scalar - juggled
function willBeJuggledToBool(bool $g){}
function willBeJuggledToString(string $h){}
function willBeJuggledToFloat(float $i){}
function willBeJuggledToInteger(integer $j){}
?>
Considering that there are no errors generated when type juggling of
scalars take place, there should be no errors when type juggling scalar
type hints for parameters.
In essence, if you are coding with scalars (ignore type hinting) and
relying on PHP to do the right thing when type juggling takes place, then
the same level of acceptance should be used when type juggling of scalar
parameters.
TL;DR; Rejecting calls to a scalar type typehinted function because the
value is of the wrong type doesn't fit with PHP's type juggling.
--
Richard Quadling
I don’t think we’re ever going to get consensus. But judging by the
feedback to the v0.1 version, I tend to disagree that the opposers would
have blocked it. There were certainly opposers – but not that many of them
as far as I could tell. I think it stood a good chance to pass at a 2/3.
Unlike strict typing – we didn’t even go to a vote on it, which I think is
unfortunate (and should be changed, before changing course completely as
this v0.2 suggests).
We’re definitely not going to have consensus on introducing both options as
per this RFC. I for one think it’s the worst possible option.
Zeev
From: Richard Quadling [mailto:rquadling@gmail.com]
Sent: Wednesday, January 14, 2015 3:23 PM
To: Zeev Suraski
Cc: Andrea Faulds; Leigh; PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Wednesday, January 14, 2015 11:33 AM
To: Leigh
Cc: PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.I don’t like the idea of being forced to use strict (or weak) type
checking
because the API author decided as much.
I don't either. But I don't like the user to do it either, it's something
that is a part of the language definition.
I completely agree with both Robert and Leigh. I liked the v0.1 one, but
v0.2 is DOA from my point of view. Arguably, from my POV, it's the one
option that's even worse than having strict typing exclusively.
Zeev
The issue of scalar type hinting has been around for a while, with various
proposals and RFCs, but no consensus. Each time a certain level of progress
is made, more issues arise.
It would seem that the major issues is that whatever a library/framework
developer decides, the user of that library/framework would have to develop
their application to fit. Is this such a bad thing? The comeback to that is
that PHP supports type juggling, so there is a different mechanism for
non-scalars to scalars. Fair enough.
From the lib developer's perspective, if a parameter to a function/method
is going to be treated as an integer and is expected to be an integer, then
they should be able to force/limit this just like they can when they say it
must be an array/callable/class/interface. But take into account the option
to enforce the type juggling.
I get 3 questions from this.
1 - Should the type hint restrict non matching types?
2 - When should the value be juggled to match the type hint if it is
different?
3 - Could we allow different signatures for the same method name? - A
different question entirely, but one that may be worth having in relation
to this proposal.
Whatever mechanism is used, it needs to be of zero effort for the user, but
fully understood of the effect.
I think to answer all of this, and to provide enough flexibility that
everyone can be made happy and understand the effect, I think the issues
could be resolved with the following.
1 - A type hint of 'scalar' is required.
This excludes other types (array/callable/class/interface) and would
specifically mean that no type juggling will take place as part of the
parameter passing.
If no type juggling is going to take place, why does it matter what the
type hint is? The advantage of having 'scalar' as a type hint is, as I
said, excludes non-scalars.
Now, if the method does something to the value and the value is passed by
reference, then that would need to be documented clearly.
2 - A scalar type type hint will automatically juggle. PHP is a dynamic
language and, as such, type juggling is used throughout. It shouldn't be
any different when a parameter is type hinted for scalars.
The frustration seems to be that without a way to say that this scalar will
NOT be type juggled (loose) or that it will be (strong) then we cannot move
forward.
Now, some of the comments related to this proposal (and others) is what to
do when the scalar type is of a different type to the parameter.
I think I've covered this by the use of the type hint 'scalar'.
Scalars get type juggled. Period. For good or bad. Until PHP becomes a
strongly type language, type juggling exists.
With the hinting, we can let users know that type juggling will now also
apply to parameters.
So.
<?php
// Any type.
function anyType($a){}
// Current types.
function anArray(array $b){}
function aCallable(callable $c){}
function aClass(stdclass $d){}
function anInterface(Countable $e){}
// Any scalar - not juggled.
function anyScalar(scalar $f){}
// Any scalar - juggled
function willBeJuggledToBool(bool $g){}
function willBeJuggledToString(string $h){}
function willBeJuggledToFloat(float $i){}
function willBeJuggledToInteger(integer $j){}
?>
Considering that there are no errors generated when type juggling of
scalars take place, there should be no errors when type juggling scalar
type hints for parameters.
In essence, if you are coding with scalars (ignore type hinting) and
relying on PHP to do the right thing when type juggling takes place, then
the same level of acceptance should be used when type juggling of scalar
parameters.
TL;DR; Rejecting calls to a scalar type typehinted function because the
value is of the wrong type doesn't fit with PHP's type juggling.
--
Richard Quadling
Hello,
personally, as a language user, I really dislike the idea of both
options for scalar type hinting to be the part of the language.
Especially since you would have to declare the strict typing in each
file (if you are going by 1 class per file in a bigger project, that's
a LOT of declare directives to write in the long run) and if you'd
forgot once, it would make the calling of methods somehow
inconsistent.
I wish there was just one way to do it; I don't care if the weak or
strong variant is going to be accepted, IMHO most programmers will be
able to adapt to either of them. The weak version makes probably more
sense for PHP and how it handles scalar types (at least from userland
developer's standpoint), but either of them is better than no
typehints at all. :)
PS: Personally, I find the "scalar" typehint idea useless and cannot
find a real use case for it. Richard, would you mind giving an
example?
Regards
Pavel Kouril
I don’t think we’re ever going to get consensus. But judging by the
feedback to the v0.1 version, I tend to disagree that the opposers would
have blocked it. There were certainly opposers – but not that many of them
as far as I could tell. I think it stood a good chance to pass at a 2/3.
Unlike strict typing – we didn’t even go to a vote on it, which I think is
unfortunate (and should be changed, before changing course completely as
this v0.2 suggests).We’re definitely not going to have consensus on introducing both options as
per this RFC. I for one think it’s the worst possible option.Zeev
From: Richard Quadling [mailto:rquadling@gmail.com]
Sent: Wednesday, January 14, 2015 3:23 PM
To: Zeev Suraski
Cc: Andrea Faulds; Leigh; PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Wednesday, January 14, 2015 11:33 AM
To: Leigh
Cc: PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.I don’t like the idea of being forced to use strict (or weak) type
checking
because the API author decided as much.I don't either. But I don't like the user to do it either, it's something
that is a part of the language definition.I completely agree with both Robert and Leigh. I liked the v0.1 one, but
v0.2 is DOA from my point of view. Arguably, from my POV, it's the one
option that's even worse than having strict typing exclusively.Zeev
The issue of scalar type hinting has been around for a while, with various
proposals and RFCs, but no consensus. Each time a certain level of progress
is made, more issues arise.It would seem that the major issues is that whatever a library/framework
developer decides, the user of that library/framework would have to develop
their application to fit. Is this such a bad thing? The comeback to that is
that PHP supports type juggling, so there is a different mechanism for
non-scalars to scalars. Fair enough.From the lib developer's perspective, if a parameter to a function/method
is going to be treated as an integer and is expected to be an integer, then
they should be able to force/limit this just like they can when they say it
must be an array/callable/class/interface. But take into account the option
to enforce the type juggling.I get 3 questions from this.
1 - Should the type hint restrict non matching types?
2 - When should the value be juggled to match the type hint if it is
different?3 - Could we allow different signatures for the same method name? - A
different question entirely, but one that may be worth having in relation
to this proposal.Whatever mechanism is used, it needs to be of zero effort for the user, but
fully understood of the effect.I think to answer all of this, and to provide enough flexibility that
everyone can be made happy and understand the effect, I think the issues
could be resolved with the following.1 - A type hint of 'scalar' is required.
This excludes other types (array/callable/class/interface) and would
specifically mean that no type juggling will take place as part of the
parameter passing.If no type juggling is going to take place, why does it matter what the
type hint is? The advantage of having 'scalar' as a type hint is, as I
said, excludes non-scalars.Now, if the method does something to the value and the value is passed by
reference, then that would need to be documented clearly.2 - A scalar type type hint will automatically juggle. PHP is a dynamic
language and, as such, type juggling is used throughout. It shouldn't be
any different when a parameter is type hinted for scalars.The frustration seems to be that without a way to say that this scalar will
NOT be type juggled (loose) or that it will be (strong) then we cannot move
forward.Now, some of the comments related to this proposal (and others) is what to
do when the scalar type is of a different type to the parameter.I think I've covered this by the use of the type hint 'scalar'.
Scalars get type juggled. Period. For good or bad. Until PHP becomes a
strongly type language, type juggling exists.With the hinting, we can let users know that type juggling will now also
apply to parameters.So.
<?php
// Any type.
function anyType($a){}
// Current types.
function anArray(array $b){}
function aCallable(callable $c){}
function aClass(stdclass $d){}
function anInterface(Countable $e){}
// Any scalar - not juggled.
function anyScalar(scalar $f){}
// Any scalar - juggled
function willBeJuggledToBool(bool $g){}
function willBeJuggledToString(string $h){}
function willBeJuggledToFloat(float $i){}
function willBeJuggledToInteger(integer $j){}
?>
Considering that there are no errors generated when type juggling of
scalars take place, there should be no errors when type juggling scalar
type hints for parameters.In essence, if you are coding with scalars (ignore type hinting) and
relying on PHP to do the right thing when type juggling takes place, then
the same level of acceptance should be used when type juggling of scalar
parameters.TL;DR; Rejecting calls to a scalar type typehinted function because the
value is of the wrong type doesn't fit with PHP's type juggling.--
Richard Quadling
2015-01-14 16:00 GMT+02:00 Pavel Kouřil pajousek@gmail.com:
Hello,
personally, as a language user, I really dislike the idea of both
options for scalar type hinting to be the part of the language.
Especially since you would have to declare the strict typing in each
file (if you are going by 1 class per file in a bigger project, that's
a LOT of declare directives to write in the long run) and if you'd
forgot once, it would make the calling of methods somehow
inconsistent.I wish there was just one way to do it; I don't care if the weak or
strong variant is going to be accepted, IMHO most programmers will be
able to adapt to either of them. The weak version makes probably more
sense for PHP and how it handles scalar types (at least from userland
developer's standpoint), but either of them is better than no
typehints at all. :)PS: Personally, I find the "scalar" typehint idea useless and cannot
find a real use case for it. Richard, would you mind giving an
example?Regards
Pavel Kouril
As a userland developer, have to agree with this message fully.
-1 on the v0.2 version, the declare() approach is gonna make our job
misserable after a few years when this gets adopted and misused by a lot of
people...
PS: Personally, I find the "scalar" typehint idea useless and cannot
find a real use case for it. Richard, would you mind giving an
example?
The point of the 'scalar' typehint comes about because we need to reject
non compatible types. Just like we do when we say array or callable.
Currently, if we want a method/function to accept a scalar, then we cannot
put any type hinting in and so we can supply an array, callable, class or
interface.
Being able to say 'scalar' would mean I can instantly inform the user that
any scalar can be used and that no type juggling will happen automatically.
For example, take ...
<?php
function sum(scalar $left, scalar $right) { return $left + $right;}
?>
Now in this example, sure the parameters will be juggled because of the +
operator.
But without the typehint, and the lack of operator overloading, you would
get an error if non-scalars are supplied in the addition, rather than in
the call. The + is fine, it is the wrong params to the function that should
be the problem. And a scalar typehint is the better place I think.
Now if we have polymorphic behaviour ...
<?php
function sum(scalar $left, scalar $right) { return $left + $right;} // Type
juggled addition
function sum(array $left, array $right) { return array_merge($left,
$right);} // Array merging
function sum(string $left, string $right) { return $left . $right;} //
String concatenation.
?>
(OK, 'sum' isn't a perfect example, but you see the point I hope).
Richard.
--
Richard Quadling
Twitter : @RQuadling
EE : http://e-e.com/M_248814.html
Zend : http://bit.ly/9O8vFY
I don’t think we’re ever going to get consensus. But judging by the
feedback to the v0.1 version, I tend to disagree that the opposers would
have blocked it. There were certainly opposers – but not that many of them
as far as I could tell. I think it stood a good chance to pass at a 2/3.
Unlike strict typing – we didn’t even go to a vote on it, which I think is
unfortunate (and should be changed, before changing course completely as
this v0.2 suggests).
Hi guys,
I completely agree. I would have gone through with voting on v0.1 first.
Then later (maybe) propose v0.2 as an improvement.
For me v0.1 is better than no hinting, and no hinting is better than v0.2.
--
Ole Markus
Hi Zeev,
I don’t think we’re ever going to get consensus. But judging by the feedback to the v0.1 version, I tend to disagree that the opposers would have blocked it. There were certainly opposers – but not that many of them as far as I could tell. I think it stood a good chance to pass at a 2/3. Unlike strict typing – we didn’t even go to a vote on it, which I think is unfortunate (and should be changed, before changing course completely as this v0.2 suggests).
We’re definitely not going to have consensus on introducing both options as per this RFC. I for one think it’s the worst possible option.
It’s certainly possible it would’ve succeeded on internals. However, it is also worth considering the opinions of those who do not frequent internals and don’t have the right to vote.
From what I can see, the larger PHP community is generally in favour of strict typing, and among them, the previous RFC revision was received quite poorly. Myself, I might have been somewhat happy with just weak hints, but it would upset an awful lot of developers who would like some measure of strict typing. Developers who would most likely not use the new scalar type hints, because they weren’t strict. And if nobody uses them, why add them?
This revision hopes to possibly placate both weak and strict typing advocates. Of course, it also will lose some support in that it allows a choice. Plus, it gives the user choice, not the API designer, which I expect will be somewhat controversial. But I am hopeful.
Thanks.
Andrea Faulds
http://ajf.me/
Andrea Faulds wrote:
From what I can see, the larger PHP community is generally in favour
of strict typing, and among them, the previous RFC revision was
received quite poorly. Myself, I might have been somewhat happy with
just weak hints, but it would upset an awful lot of developers who
would like some measure of strict typing. Developers who would most
likely not use the new scalar type hints, because they weren’t
strict. And if nobody uses them, why add them?This revision hopes to possibly placate both weak and strict typing
advocates. Of course, it also will lose some support in that it
allows a choice. Plus, it gives the user choice, not the API
designer, which I expect will be somewhat controversial. But I am
hopeful.
Just a thought: what about having weak scalar type hints which throw
E_STRICT_TYPE if a value of another type is passed?
--
Christoph M. Becker
From what I can see, the larger PHP community is generally in favour of strict typing, and among them, the previous RFC revision was received quite poorly. Myself, I might have been somewhat happy with just weak hints, but it would upset an awful lot of developers who would like some measure of strict typing. Developers who would most likely not use the new scalar type hints, because they weren’t strict. And if nobody uses them, why add them?
Actually, what's the big difference, making weak typing worse and less
useable? The people who write libraries are guaranteed either way that
the input parameters for their methods will be of desired type in both
cases. And the people who use them either can do the conversion
themselves (in strong typing case) or let the language help with it
for them (in weak typing case) - which is IMHO fine, as long as the
conversions are kinda predictable and 100% documented.
And yesterday I was pointed out one thing: the RFC states "With this
approach, an argument is only accepted if its type is exactly the same
as the parameter.". Does this mean you cannot pass integer to a
function with float argument in the strict mode?
Is it strong or strict, btw? I always thought it's supposed to be
"strongly typed", but since I saw "strict typing" here used by
everyone, I'm not sure now.
Pavel Kouril
And yesterday I was pointed out one thing: the RFC states "With this
approach, an argument is only accepted if its type is exactly the same
as the parameter.". Does this mean you cannot pass integer to a
function with float argument in the strict mode?
One of the nice features of PHP when I started using it all those years
ago was that I did not have to create separate functions different types
did exist in the source data. int/float/num/double and others all needed
separate handling in c/c++, and one could not easily add a different
'type' of data.
Nowadays I get around many of the problems that are currently all being
debated by passing an 'id' or an array of data as the only parameter to
a function. If the bigint 'id' is already loaded, the cached version is
used, if not it is loaded or an empty default object created. If an
array is passed then the relevant fields are actioned. With the current
discussions I see what has become a style of working based on how PHP
USED to work is now being pushed into the 'that is not the way to do it'
box? I have named parameters, they are the elements of the array, order
is not relevant, I can skip ones, or add new ones without affecting
anything.
I can see that for some nailing everything down and avoiding any
flexibility is their target while others DO still subscribe to the
lighter approach which allows in my book greater flexibility. So perhaps
we are at a point where a big switch is needed much like e_strict to
isolate the 'strict mode' from 'flexible mode'?
I can see third party libraries having to provide different versions of
the same code if this particular discussion goes down the wrong path?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
One of the nice features of PHP when I started using it all those years
ago was that I did not have to create separate functions different types
did exist in the source data. int/float/num/double and others all needed
separate handling in c/c++, and one could not easily add a different
'type' of data.
If you have a function which requires a "double" in C# (a strongly
typed language), you can safely pass int to the function and it will
work, because you are not narrowing the possible values. So making the
PHP accept only the argument if its type is exactly the same as the
parameter (paraphrased from RFC for the strict version of type hints)
seems like a step in a wrong direction. If I'm not mistaken, Java
behaves the same way. How exactly does it work in C++ and C? I haven't
used C in years, so I'm a little bit rusty on this detail.
Pavel Kouril
One of the nice features of PHP when I started using it all those years
ago was that I did not have to create separate functions different types
did exist in the source data. int/float/num/double and others all needed
separate handling in c/c++, and one could not easily add a different
'type' of data.If you have a function which requires a "double" in C# (a strongly
typed language), you can safely pass int to the function and it will
work, because you are not narrowing the possible values. So making the
PHP accept only the argument if its type is exactly the same as the
parameter (paraphrased from RFC for the strict version of type hints)
seems like a step in a wrong direction. If I'm not mistaken, Java
behaves the same way. How exactly does it work in C++ and C? I haven't
used C in years, so I'm a little bit rusty on this detail.
I'm going back 15 years here ;)
I still have code with several functions which are essentially the same
because they wrap the same core function, but on moving to PHP all the
wrappers fall away and one just adds the 'conversion/validation' in the
function. e_strict has already brought back the need for extra versions
of functions for static and dynamic access and adding typing potentially
extends that.
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Thursday, January 15, 2015 12:29 AM
To: Zeev Suraski
Cc: RQuadling@gmail.com; Leigh; PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Zeev,
I don’t think we’re ever going to get consensus. But judging by the
feedback to the v0.1 version, I tend to disagree that the opposers would
have blocked it. There were certainly opposers – but not that many of
them
as far as I could tell. I think it stood a good chance to pass at a 2/3.
Unlike
strict typing – we didn’t even go to a vote on it, which I think is
unfortunate
(and should be changed, before changing course completely as this v0.2
suggests).We’re definitely not going to have consensus on introducing both options
as per this RFC. I for one think it’s the worst possible option.It’s certainly possible it would’ve succeeded on internals. However, it is
also
worth considering the opinions of those who do not frequent internals and
don’t have the right to vote.From what I can see, the larger PHP community is generally in favour of
strict
typing, and among them, the previous RFC revision was received quite
poorly.
Andrea,
I'm not sure what you're basing that assumption on. The incidental
interactions you (or anybody) may have with 'the community', by no way
represent the opinion of the community at large. The vast majority of the
PHP community never ever interacts with internals@, never attend
conferences, don't write blog posts about PHP and are generally completely
'under the radar'. I would actually go to argue that the people who do
attend conferences, participate on internals@ or write blog posts - are not
representative of the PHP userbase at large. The vast majority of
developers I bump into - you will never ever hear from. They constitute the
vast majority of the ~5M strong PHP developer base.
So even though my belief / educated guess is that the vast majority of the
PHP userbase would prefer to see strict typing kept off this language, I'm
not going to argue that - but we must not argue the opposite either, based
on the non-representative anecdotal data from a few dozen people.
Myself, I might have been somewhat happy with just weak hints, but
it would upset an awful lot of developers who would like some measure of
strict typing. Developers who would most likely not use the new scalar
type
hints, because they weren’t strict. And if nobody uses them, why add them?
How do you deduce that 'nobody uses them' from the fact that some group of
people said they won't? I'm sorry, but it makes no sense, especially given
the positive feedback you saw on internals, making it clear that there would
be in fact people using it. Note that unlike the opposition to strong
typing - which has always been about the fact that the concept of strict
typing is alien to and inconsistent with rest of PHP - the opposition to
auto-casting typing is "I won't use it because it doesn't do what I'd like
it to do". People who don't want to use it won't use it, but based on the
feedback v0.1 received, it was clear plenty of people would.
This revision hopes to possibly placate both weak and strict typing
advocates. Of course, it also will lose some support in that it allows a
choice.
Plus, it gives the user choice, not the API designer, which I expect will
be
somewhat controversial. But I am hopeful.
I'm not sure what to say, so I'll repeat what I said before.
If there's one thing that's worse than introducing an alien concept like
strict typing into PHP, it's introducing it as a feature that will include
all the negatives of this alien concept, PLUS have the ability to radically
change how it behaves based on a runtime option. It's so bad that we
decided more than a decade ago that we want to refrain from ever introducing
such elements to PHP again (e.g. magic_quotes_runtime), and I'm not sure why
we're even discussing it.
To be honest, before you wrote the v0.1 RFC I was talking with Dmitry
regarding the possibility of writing one up myself. You saved me a lot of
work by working on one. I hope that based on the feedback from numerous
people here you'll abandon v0.2, but if not, I'd want take over v0.1 of the
RFC and propose it as an alternative. v0.2 as disastrous for PHP.
Zeev
Zeev Suraski wrote on 15/01/2015 11:56:
PLUS have the ability to radically
change how it behaves based on a runtime option. It's so bad that we
decided more than a decade ago that we want to refrain from ever introducing
such elements to PHP again (e.g. magic_quotes_runtime), and I'm not sure why
we're even discussing it.
Just on this point, I do think declare() is potentially less evil than
ini_set()
/ php.ini. A declare() directive is scoped to a particular
section of code, so library authors shouldn't need to care which setting
their users prefer, only the version they themselves wish to use. This
contrasts completely with things like mbstring.func_overload, which
makes shared library code run differently in different configurations.
As has been clarified elsewhere on this thread, under this proposal a
library author writing function foo(int $foo) will ALWAYS receive an
integer, regardless of how that integer is arrived at. Very
approximately, the declare() directive effectively gives the caller a
choice between two pieces of syntactic sugar, both of which guarantee
that the callee's contract will be met:
if ( is_int($foo) ) { foo($foo); } else { raise_type_error($foo); }
or
foo ( (int)$foo );
So, just to repeat, this is NOT like register_globals or
mbstring.func_overload, because shared code never needs to handle both
settings.
That's not to say I'm 100% convinced that this is the right way to go,
just that it's not as abominable as some people are making out.
Regards,
Rowan Collins
[IMSoP]
Hey Rowan,
Zeev Suraski wrote on 15/01/2015 11:56:
PLUS have the ability to radically
change how it behaves based on a runtime option. It's so bad that we
decided more than a decade ago that we want to refrain from ever introducing
such elements to PHP again (e.g. magic_quotes_runtime), and I'm not sure why
we're even discussing it.Just on this point, I do think declare() is potentially less evil than
ini_set()
/ php.ini. A declare() directive is scoped to a particular section of code, so library authors shouldn't need to care which setting their users prefer, only the version they themselves wish to use. This contrasts completely with things like mbstring.func_overload, which makes shared library code run differently in different configurations.
Yeah, that’s the idea behind it. The hope is that you could have strictly-typed and weakly-typed code interact seamlessly with minimal issues. And, for the most part, this should allow that.
A large part of the motivation behind this was avoiding the problems that adding separate strict and weak hints would have. Inevitably, people who were fans of weak typing would use a weak hint all the time, and people who were fans of strict typing would use a strict hint all the time. There would also be the odd few who might mix them, but I don’t think that would happen terribly much.
It’s much easier to deal with this:
foo(1.0, 1); // strict
$qux = bar(“foo”); // also strict
foobar($qux, baz(true)); // also strict
or this:
foo(1.0, 1); // weak
$qux = bar(“foo”); // also weak
foobar($qux, baz(true)); // also weak
Than it would be to have to deal with this:
foo(1.0, 1); // weak
$qux = bar(“foo”); // strict
foobar($qux, baz(true)); // baz is strict, foobar is weak
This RFC would guarantee that, for the most part, you’re dealing with the first case (strict mode) or the second case (default). I fear that separate strict and weak hints would result in the third case being commonplace.
I was also worried that if we just added weak hints, people who didn’t like them would not use them and instead use manual assertions. Similarly, I think something similar might happen if we just added strict hints. In both cases, you would be ending up with the third situation. Also bear in mind that if we added strict hints and did not change the behaviour of extension and built-in PHP functions, we’d also be dealing with that third situation, since zend_parse_parameters essentially does a kind of weak typing.
Of course, this RFC does still lead to dealing with both weak and strict modes sometimes, but at least it’d always be the same mode within a given file, and by extension, within a given function, method or class. I think that’s more practical than dealing with two or more different modes within three lines of code.
As has been clarified elsewhere on this thread, under this proposal a library author writing function foo(int $foo) will ALWAYS receive an integer, regardless of how that integer is arrived at. Very approximately, the declare() directive effectively gives the caller a choice between two pieces of syntactic sugar, both of which guarantee that the callee's contract will be met:
if ( is_int($foo) ) { foo($foo); } else { raise_type_error($foo); }
or
foo ( (int)$foo );
So, just to repeat, this is NOT like register_globals or mbstring.func_overload, because shared code never needs to handle both settings.
That's not to say I'm 100% convinced that this is the right way to go, just that it's not as abominable as some people are making out.
Right.
Andrea Faulds
http://ajf.me/
Hi Zeev,
Andrea,
I'm not sure what you're basing that assumption on. The incidental
interactions you (or anybody) may have with 'the community', by no way
represent the opinion of the community at large. The vast majority of the
PHP community never ever interacts with internals@, never attend
conferences, don't write blog posts about PHP and are generally completely
'under the radar'. I would actually go to argue that the people who do
attend conferences, participate on internals@ or write blog posts - are not
representative of the PHP userbase at large. The vast majority of
developers I bump into - you will never ever hear from. They constitute the
vast majority of the ~5M strong PHP developer base.So even though my belief / educated guess is that the vast majority of the
PHP userbase would prefer to see strict typing kept off this language, I'm
not going to argue that - but we must not argue the opposite either, based
on the non-representative anecdotal data from a few dozen people.
Whether or not they are in the majority, a very large portion of PHP developers would prefer strict typing. In particular, the most vocal ones would seem to. There are also a lot of PHP developers who would prefer weak typing. Thus we have a problem: either approach to scalar hints will upset a large portion of the community.
Myself, I might have been somewhat happy with just weak hints, but
it would upset an awful lot of developers who would like some measure of
strict typing. Developers who would most likely not use the new scalar
type
hints, because they weren’t strict. And if nobody uses them, why add them?How do you deduce that 'nobody uses them' from the fact that some group of
people said they won't? I'm sorry, but it makes no sense, especially given
the positive feedback you saw on internals, making it clear that there would
be in fact people using it.
Not all of it was positive. Sure, a lot of people would use them though, but I’ve heard quite a few developers say they wouldn’t use them and continue to use manual (!is_int($foo))-style assertions.
If there's one thing that's worse than introducing an alien concept like
strict typing into PHP, it's introducing it as a feature that will include
all the negatives of this alien concept, PLUS have the ability to radically
change how it behaves based on a runtime option.
This isn’t a runtime option, it is entirely compile-time. Much like namespaces are not a runtime option. There isn’t even the ability to toggle it at runtime, unless we somehow add some ability to edit the flags on individual opcodes.
Thanks.
--
Andrea Faulds
http://ajf.me/
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Thursday, January 15, 2015 4:10 PM
To: Zeev Suraski
Cc: RQuadling@gmail.com; Leigh; PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Zeev,
Whether or not they are in the majority, a very large portion of PHP
developers would prefer strict typing. In particular, the most vocal ones
would seem to. There are also a lot of PHP developers who would prefer
weak typing. Thus we have a problem: either approach to scalar hints will
upset a large portion of the community.
That's correct. As I said though, the source of the opposition is
fundamentally different.
The camp which opposes weak typing opposes it based on the idea that it
doesn't behave in the way that would suit their needs.
The camp which opposes strict typing - which incidentally includes most of
the people who originally created the language - opposes it based on the
assertion that it goes against the spirit of the language. That is equally
true for the v0.2 proposal you've just submitted.
How do you deduce that 'nobody uses them' from the fact that some
group of people said they won't? I'm sorry, but it makes no sense,
especially given the positive feedback you saw on internals, making it
clear that there would be in fact people using it.Not all of it was positive. Sure, a lot of people would use them though,
but
I’ve heard quite a few developers say they wouldn’t use them and continue
to use manual (!is_int($foo))-style assertions.
Of course not all of it was positive, but it was overwhelmingly positive.
Very few opposed. Someone saying they won't use it doesn't count as
opposition. You see, PHP exists for 15-20 years now. There aren't any
must-have features that aren't in it. No single feature we add will be used
by everyone, and people telling us they won't use this feature shouldn't
'deter' us in any way.
If there's one thing that's worse than introducing an alien concept
like strict typing into PHP, it's introducing it as a feature that
will include all the negatives of this alien concept, PLUS have the
ability to radically change how it behaves based on a runtime option.This isn’t a runtime option, it is entirely compile-time. Much like
namespaces
are not a runtime option. There isn’t even the ability to toggle it at
runtime,
unless we somehow add some ability to edit the flags on individual
opcodes.
Compile time and runtime in PHP are intertwined when you factor in
cross-file interaction.
Zeev
Hi Zeev,
Whether or not they are in the majority, a very large portion of PHP
developers would prefer strict typing. In particular, the most vocal ones
would seem to. There are also a lot of PHP developers who would prefer
weak typing. Thus we have a problem: either approach to scalar hints will
upset a large portion of the community.That's correct. As I said though, the source of the opposition is
fundamentally different.
The camp which opposes weak typing opposes it based on the idea that it
doesn't behave in the way that would suit their needs.
The camp which opposes strict typing - which incidentally includes most of
the people who originally created the language - opposes it based on the
assertion that it goes against the spirit of the language. That is equally
true for the v0.2 proposal you've just submitted.
I’m not really sure this is true. I agree that strict types aren’t entirely in keeping with the “PHP way”. However, there are plenty of people who are against them not for that reason, but simply because they don’t work well for them. Plus, I’m not sure strict typing causes as much of a problem if it is off by default. Nobody is forced to use it, the language would stay beginner-friendly and weakly-typed. Indeed, strict type hints don’t stop PHP being weakly-typed. They just check types at function call boundaries. Think of it as a sanity check.
How do you deduce that 'nobody uses them' from the fact that some
group of people said they won't? I'm sorry, but it makes no sense,
especially given the positive feedback you saw on internals, making it
clear that there would be in fact people using it.Not all of it was positive. Sure, a lot of people would use them though,
but
I’ve heard quite a few developers say they wouldn’t use them and continue
to use manual (!is_int($foo))-style assertions.Of course not all of it was positive, but it was overwhelmingly positive.
Very few opposed. Someone saying they won't use it doesn't count as
opposition.
Let’s have a look. From a quick skim over the thread for v0.1:
- In favour of weak types (or the RFC anyway): Adam, Stas, yourself, Jordi, Pierre,
- Against, in favour of strict types: Maxime, Nikita, Markus, Marco, Leigh, Levi, Sven(?)
- In favour of strict types, not against weak types as compromise: Matthew
- Somewhat in favour: Sebastian
- In favour of allowing both approaches: Marcio, Thomas, Marco
I apologise if I am misrepresenting anyone’s position.
This is unlikely to be super-representative of the PHP community. However, I’m not sure I’d say “overwhelmingly positive”. It can be easy to get confirmation bias when reading RFC threads.
It is very clear to me that a lot of people would like strict types, and some people would like weak types. As to their relative numbers, I cannot say.
I don’t think it’s really fair to cover only the use case of one half of the PHP community. The other half counts too. This is a rather divisive issue.
You see, PHP exists for 15-20 years now. There aren't any
must-have features that aren't in it. No single feature we add will be used
by everyone, and people telling us they won't use this feature shouldn't
'deter' us in any way.
I don’t think this is true: if we are making a feature less useful (and therefore making many people avoid it), it’s worth considering if that is a problem. If we can easily cover the vast majority of people’s use cases, rather than catering to only one group of people (who may or may not be the majority), why don’t we?
If there's one thing that's worse than introducing an alien concept
like strict typing into PHP, it's introducing it as a feature that
will include all the negatives of this alien concept, PLUS have the
ability to radically change how it behaves based on a runtime option.This isn’t a runtime option, it is entirely compile-time. Much like
namespaces
are not a runtime option. There isn’t even the ability to toggle it at
runtime,
unless we somehow add some ability to edit the flags on individual
opcodes.Compile time and runtime in PHP are intertwined when you factor in
cross-file interaction.
Except that is not the case for this proposal, which explicitly and deliberately prevents the directive affecting inclusion. The behaviour is impossible to toggle at runtime, unless you’re using some weird extension which lets you edit the flag on the ZEND_DO_FCALL opcode.
Thanks!
--
Andrea Faulds
http://ajf.me/
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Thursday, January 15, 2015 4:51 PM
To: Zeev Suraski
Cc: RQuadling@gmail.com; Leigh; PHP Internals List
Subject: Re: [PHP-DEV] [RFC] Scalar Type Hints v0.2Hi Zeev,
Whether or not they are in the majority, a very large portion of PHP
developers would prefer strict typing. In particular, the most vocal
ones would seem to. There are also a lot of PHP developers who would
prefer weak typing. Thus we have a problem: either approach to scalar
hints will upset a large portion of the community.That's correct. As I said though, the source of the opposition is
fundamentally different.
The camp which opposes weak typing opposes it based on the idea that
it doesn't behave in the way that would suit their needs.
The camp which opposes strict typing - which incidentally includes
most of the people who originally created the language - opposes it
based on the assertion that it goes against the spirit of the
language. That is equally true for the v0.2 proposal you've just
submitted.I’m not really sure this is true. I agree that strict types aren’t
entirely in
keeping with the “PHP way”. However, there are plenty of people who are
against them not for that reason, but simply because they don’t work well
for them. Plus, I’m not sure strict typing causes as much of a problem if
it is
off by default. Nobody is forced to use it, the language would stay
beginner-
friendly and weakly-typed. Indeed, strict type hints don’t stop PHP being
weakly-typed. They just check types at function call boundaries. Think of
it as
a sanity check.How do you deduce that 'nobody uses them' from the fact that some
group of people said they won't? I'm sorry, but it makes no sense,
especially given the positive feedback you saw on internals, making
it clear that there would be in fact people using it.Not all of it was positive. Sure, a lot of people would use them
though, but I’ve heard quite a few developers say they wouldn’t use
them and continue to use manual (!is_int($foo))-style assertions.Of course not all of it was positive, but it was overwhelmingly
positive.
Very few opposed. Someone saying they won't use it doesn't count as
opposition.Let’s have a look. From a quick skim over the thread for v0.1:
- In favour of weak types (or the RFC anyway): Adam, Stas, yourself,
Jordi,
Pierre,
You're definitely missing Dmitry (which helped with the RFC) as well as
Xinchen and Arvids from today. From past experience I believe Rasmus too.
- Against, in favour of strict types: Maxime, Nikita, Markus, Marco,
Leigh,
Levi, Sven(?)
As far as I recall (maybe I'm wrong) the only one here that outright opposed
was Nikita. Others suggested ways to improve it but didn't really oppose
it.
This is unlikely to be super-representative of the PHP community. However,
I’m not sure I’d say “overwhelmingly positive”. It can be easy to get
confirmation bias when reading RFC threads.
Fair enough.
It is very clear to me that a lot of people would like strict types, and
some
people would like weak types. As to their relative numbers, I cannot say.
Well, that's clear bias right here too - 'a lot' vs. 'some'. Again, I don't
think you have a way of knowing it and based on my experience the opposite
is true - but none of us truly knows. Either way, the former goes against
what we created PHP around, while the latter does not.
I don’t think it’s really fair to cover only the use case of one half of
the PHP
community. The other half counts too. This is a rather divisive issue.
I disagree. PHP has never been about everything and the kitchen sink. Not
only do we not strive to support everyone's taste, we actually try not to,
and be somewhat opinionated on how things should be done.
This issue is primarily divisive among the inner core of the PHP userbase,
hardly around the millions of users out there.
You see, PHP exists for 15-20 years now. There aren't any must-have
features that aren't in it. No single feature we add will be used by
everyone, and people telling us they won't use this feature shouldn't
'deter' us in any way.I don’t think this is true: if we are making a feature less useful (and
therefore
making many people avoid it), it’s worth considering if that is a problem.
If
we can easily cover the vast majority of people’s use cases, rather than
catering to only one group of people (who may or may not be the majority),
why don’t we?
For the same reason we didn't introduce strict types in the countless times
it came up in the past - it goes against the language's principles.
Except that is not the case for this proposal, which explicitly and
deliberately
prevents the directive affecting inclusion. The behaviour is impossible to
toggle at runtime, unless you’re using some weird extension which lets you
edit the flag on the ZEND_DO_FCALL opcode.
Fact is that people who run websites where they don't care about strict
typing, can end up viewing strict type failures coming from code they don't
own, which would make the app fail 'catastophically' and unpredictably.
You'd have no way to turn it off (without diving to and changing the file in
question) - because it's the code itself that turns it on - and from the
user's point of view, for all practical purposes, at runtime.
I agree that the scope of breakage of using a local file definition is much
reduced compared to an INI entry, but it's still there.
Zeev
Except that is not the case for this proposal, which explicitly and
deliberately
prevents the directive affecting inclusion. The behaviour is impossible to
toggle at runtime, unless you’re using some weird extension which lets you
edit the flag on the ZEND_DO_FCALL opcode.Fact is that people who run websites where they don't care about strict
typing, can end up viewing strict type failures coming from code they don't
own, which would make the app fail 'catastophically' and unpredictably.
You'd have no way to turn it off (without diving to and changing the file in
question) - because it's the code itself that turns it on - and from the
user's point of view, for all practical purposes, at runtime.I agree that the scope of breakage of using a local file definition is much
reduced compared to an INI entry, but it's still there.
I agree that's a bad situation, but if a library uses strict types via
declare, it is likely that it would also use scalar hints on its own
method definitions. Not doing so would be irresponsible IMO as you'd
indeed expose your API's users to strict failures.
If you do use strict types + scalar hints, a user passing random data
from a non-strict file would never get a failure as the data would be
coerced before reaching the strict library.
Right now, or with only weak hints, if a library decides to implement
strict typing, they'll skip the scalar hints and check types with
something like the assert lib [1]. A user calling it with random data
would always get exceptions. There is no way for the library to use
scalar hints to play nice with weak-typed callers as it would not be
able to type check anymore in that case.
That is the value I see in the declare() proposal, although whether it's
declare() or some other way to enable this per file I don't really care.
[1] https://github.com/beberlei/assert
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
Right now, or with only weak hints, if a library decides to implement strict
typing, they'll skip the scalar hints and check types with something like
the assert lib [1]. A user calling it with random data would always get
exceptions. There is no way for the library to use scalar hints to play nice
with weak-typed callers as it would not be able to type check anymore in
that case.
Why would the libraries writers use the checks inside the method
instead of the typing, even in the case of the weak typing? I don't
see a single reason to do so, because if they ask for an "int" in the
method signature, they will get an int or the method won't get called
at all. See the example in the RFC with the "if (!is_int($i))".
Pavel Kouril
Right now, or with only weak hints, if a library decides to implement strict
typing, they'll skip the scalar hints and check types with something like
the assert lib [1]. A user calling it with random data would always get
exceptions. There is no way for the library to use scalar hints to play nice
with weak-typed callers as it would not be able to type check anymore in
that case.Why would the libraries writers use the checks inside the method
instead of the typing, even in the case of the weak typing? I don't
see a single reason to do so, because if they ask for an "int" in the
method signature, they will get an int or the method won't get called
at all. See the example in the RFC with the "if (!is_int($i))".
I mean that if someone wants strict typing they won't want to use weak
hints because that would coerce the data before they can verify it and
ensure their code is strictly typed.
Therefore the best course of action is to have no hint + check manually,
like they are doing now with such libs.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
I mean that if someone wants strict typing they won't want to use weak hints
because that would coerce the data before they can verify it and ensure
their code is strictly typed.Therefore the best course of action is to have no hint + check manually,
like they are doing now with such libs.
I'm sorry, but I still don't follow.
For the writer of a library, he is always guaranteed to get the types
he wants (declared in typehints) and therefore checking inside the
method doesn't really make any sense. Or are you saying that
developers would use checks inside of methods instead of typehints,
even if the RFC passed in its current state with the declare()
statement?
--
Pavel Kouril
I mean that if someone wants strict typing they won't want to use weak hints
because that would coerce the data before they can verify it and ensure
their code is strictly typed.Therefore the best course of action is to have no hint + check manually,
like they are doing now with such libs.I'm sorry, but I still don't follow.
For the writer of a library, he is always guaranteed to get the types
he wants (declared in typehints) and therefore checking inside the
method doesn't really make any sense. Or are you saying that
developers would use checks inside of methods instead of typehints,
even if the RFC passed in its current state with the declare()
statement?
No I am saying if it passes without declare then people wishing to use
strict types would have to build their own typing, effectively removing
the choice from these library's users as to whether they want strict
hints or not.
It's just an argument in favor of having declare().
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
Hi,
Right now, or with only weak hints, if a library decides to implement strict
typing, they'll skip the scalar hints and check types with something like
the assert lib [1]. A user calling it with random data would always get
exceptions. There is no way for the library to use scalar hints to play nice
with weak-typed callers as it would not be able to type check anymore in
that case.Why would the libraries writers use the checks inside the method
instead of the typing, even in the case of the weak typing? I don't
see a single reason to do so, because if they ask for an "int" in the
method signature, they will get an int or the method won't get called
at all. See the example in the RFC with the "if (!is_int($i))".
You're basically asking what's the difference between weak and strong
typing ... it's rather philosophical. It's the intent that's
important, not the end result, which is why I see the
caller-controlled switch as pointless.
Cheers,
Andrey.
Hi Zeev,
Let’s have a look. From a quick skim over the thread for v0.1:
- In favour of weak types (or the RFC anyway): Adam, Stas, yourself,
Jordi,
Pierre,You're definitely missing Dmitry (which helped with the RFC) as well as
Xinchen and Arvids from today. From past experience I believe Rasmus too.
Yeah, I’m probably missing one or two from skimming over the previous RFC thread.
- Against, in favour of strict types: Maxime, Nikita, Markus, Marco,
Leigh,
Levi, Sven(?)As far as I recall (maybe I'm wrong) the only one here that outright opposed
was Nikita. Others suggested ways to improve it but didn't really oppose
it.
Maybe. I don’t think Nikita was the only one opposed, but I may be wrong.
It is very clear to me that a lot of people would like strict types, and
some
people would like weak types. As to their relative numbers, I cannot say.Well, that's clear bias right here too - 'a lot' vs. 'some'. Again, I don't
think you have a way of knowing it and based on my experience the opposite
is true - but none of us truly knows. Either way, the former goes against
what we created PHP around, while the latter does not.
Tradition isn’t everything.
I don’t think it’s really fair to cover only the use case of one half of
the PHP
community. The other half counts too. This is a rather divisive issue.I disagree. PHP has never been about everything and the kitchen sink. Not
only do we not strive to support everyone's taste, we actually try not to,
and be somewhat opinionated on how things should be done.
This issue is primarily divisive among the inner core of the PHP userbase,
hardly around the millions of users out there.
Supporting strict types isn’t “everything and the kitchen sink”. Sure, we do not need to cater to everyone’s taste. But we shouldn’t do things which are unpopular, and weak types, depending on who you talk to, would be that. Strict types have a lot of support from parts of the community.
I don’t think this is true: if we are making a feature less useful (and
therefore
making many people avoid it), it’s worth considering if that is a problem.
If
we can easily cover the vast majority of people’s use cases, rather than
catering to only one group of people (who may or may not be the majority),
why don’t we?For the same reason we didn't introduce strict types in the countless times
it came up in the past - it goes against the language's principles.
It is not necessarily in conflict. We have, after all, had strict typing for non-scalars for, what, a decade now?
Except that is not the case for this proposal, which explicitly and
deliberately
prevents the directive affecting inclusion. The behaviour is impossible to
toggle at runtime, unless you’re using some weird extension which lets you
edit the flag on the ZEND_DO_FCALL opcode.Fact is that people who run websites where they don't care about strict
typing, can end up viewing strict type failures coming from code they don't
own, which would make the app fail 'catastophically' and unpredictably.
That can happen in any case. Failures in libraries will always cause problems for users. If the library is broken, the user is screwed anyhow, there’s very little they can do about it.
You'd have no way to turn it off (without diving to and changing the file in
question) - because it's the code itself that turns it on - and from the
user's point of view, for all practical purposes, at runtime.
In what way is it “at runtime”? It’s a per-file setting. What it does is no different from manual assertions on each line of code.
“Runtime” implies something that can actually be changed at, well, runtime. This can’t.
Are you opposed to people using type assertions in their own code (not entirely uncommon) along the same lines? The following two code snippets are essentially equivalent:
declare(strict_typehints=TRUE) {
foo($bar, $baz); // foo() takes an integer and a string
}
vs.
if (!is_int($bar)) {
throw new Exception(“Not an integer”);
}
if (!is_string($baz)) {
throw new Exception(“Not a string”);
}
foo($bar, $baz);
It is a property of the code, it’s not “at runtime”.
Heck, if code in a library that you’re using breaks because of strict hints, you probably can’t fix it anyway because something was probably seriously wrong.
--
Andrea Faulds
http://ajf.me/
Let’s have a look. From a quick skim over the thread for v0.1:
- In favour of weak types (or the RFC anyway): Adam, Stas, yourself, Jordi, Pierre,
Count me in for v0.1.
--
Regards,
Mike
I’m not really sure this is true. I agree that strict types aren’t entirely in keeping with the “PHP way”. However, there are plenty of people who are against them not for that reason, but simply because they don’t work well for them. Plus, I’m not sure strict typing causes as much of a problem if it is off by default. Nobody is forced to use it, the language would stay beginner-friendly and weakly-typed. Indeed, strict type hints don’t stop PHP being weakly-typed. They just check types at function call boundaries. Think of it as a sanity check.
Let’s have a look. From a quick skim over the thread for v0.1:
- In favour of weak types (or the RFC anyway): Adam, Stas, yourself, Jordi, Pierre,
- Against, in favour of strict types: Maxime, Nikita, Markus, Marco, Leigh, Levi, Sven(?)
- In favour of strict types, not against weak types as compromise: Matthew
- Somewhat in favour: Sebastian
- In favour of allowing both approaches: Marcio, Thomas, Marco
I apologise if I am misrepresenting anyone’s position.
This is unlikely to be super-representative of the PHP community. However, I’m not sure I’d say “overwhelmingly positive”. It can be easy to get confirmation bias when reading RFC threads.
It is very clear to me that a lot of people would like strict types, and some people would like weak types. As to their relative numbers, I cannot say.
I don’t think it’s really fair to cover only the use case of one half of the PHP community. The other half counts too. This is a rather divisive issue.
Man, oh man. I thought we finally had a proposal with 0.1 that everyone could give a thumbs up to and move forward. One that enables stronger type stability (for those who want it) and even can allow for under-the-hood optimizations.
I really think we took a step back with 0.2. I think a super strict approach is really against what PHP is about.
And a configuration option that significantly impacts how the language behaves is probably the worst thing we could do. I remember I bumped into something like that with Visual Basic and expression short circuiting (yes the first version didn’t have that and it became a configuration option). Completely horrible and unmaintainable.
We cannot have a configuration option that changes the core language behavior. That is a no-no and there’s a good reason why languages stay away from that.
And definitely disappointed that we took a step back after it seemed we could finally come to an agreement on this agonizing topic.
Andi
Many developers PHP offers dual syntax:
-
Strict
function bar(int $num){} -
Lax
function bar((int) $num){}
Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:
Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?
This idea has been so recurrent and yet systematically ignored by RFC
owners. Why? I think that we need to baby step and try to approve coercive
type declarations first and decide upon a possible stricter type check
later:
How a bout a reboot of what ircmaxell@php.net already started in
https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?
PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea
then v0.1 instantly becomes more acceptable", we still have time to try
some alternatives.
Am 15.01.2015 um 20:45 schrieb Marcio Almada:
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?This idea has been so recurrent and yet systematically ignored by RFC
owners. Why? I think that we need to baby step and try to approve coercive
type declarations first and decide upon a possible stricter type check
later:How a bout a reboot of what ircmaxell@php.net already started in
https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea
then v0.1 instantly becomes more acceptable", we still have time to try
some alternatives.
A function only defines the arguments and types it requires and not
where the arguments comes from. Casting is part of "Where the arguments
comes from"
Marc
Hi!
Strict
function bar(int $num){}Lax
function bar((int) $num){}
I would rather have int $num for coercive typing - given that close to
100% of existing typed functions - namely internal functions - mean
exactly that and are actually documented with this exact syntax. Yes,
there are some functions that do strict, but those are in most cases are
either close to bugs which nobody cares to fix since it's so narrow a
case or some very special cases of some complex API where type matters
for API-specific reasons.
As for strict, maybe it can be int! $num or something like that. I'm not
exactly supporting it, but out of what I have seen this would make the
most sense for me - it expresses the intent pretty clearly ("give me
int! or else!" :) and does not conflict with existing stuff.
Putting it on the table as a brainstorming exercise.
--
Stas Malyshev
smalyshev@gmail.com
Stanislav Malyshev,
I would rather have int $num for coercive typing - given that close to
100% of existing typed functions - namely internal functions - mean
exactly that and are actually documented with this exact syntax.
[...]
As for strict, maybe it can be int! $num or something like that. I'm not
exactly supporting it, but out of what I have seen this would make the
most sense for me - it expresses the intent pretty clearly ("give me
int! or else!" :) and does not conflict with existing stuff.
The hole point (at least for me) for being against function bar(int $num){}
to achieve type coercion is that the syntactic equivalent
code function bar(array $numbers){}
won't do any coercion - (array)
$numbers - because BC break would be too big to handle.
Having int|integer|bool|float|real|string
as coercive type hints
while array
is "strict" looks like an ugly hack (no pun intended).
2015-01-15 21:32 GMT-03:00 Stanislav Malyshev smalyshev@gmail.com:
Hi!
Strict
function bar(int $num){}Lax
function bar((int) $num){}I would rather have int $num for coercive typing - given that close to
100% of existing typed functions - namely internal functions - mean
exactly that and are actually documented with this exact syntax. Yes,
there are some functions that do strict, but those are in most cases are
either close to bugs which nobody cares to fix since it's so narrow a
case or some very special cases of some complex API where type matters
for API-specific reasons.As for strict, maybe it can be int! $num or something like that. I'm not
exactly supporting it, but out of what I have seen this would make the
most sense for me - it expresses the intent pretty clearly ("give me
int! or else!" :) and does not conflict with existing stuff.Putting it on the table as a brainstorming exercise.
--
Stas Malyshev
smalyshev@gmail.com
Hi!
The hole point (at least for me) for being against
function bar(int $num){}
to achieve type coercion is that the syntactic equivalent
codefunction bar(array $numbers){}
won't do any coercion - (array)
$numbers - because BC break would be too big to handle.Having
int|integer|bool|float|real|string
as coercive type hints
whilearray
is "strict" looks like an ugly hack (no pun intended).
That's how all internal functions work. It looks like you didn't
actually read my argument but just repeated "I want my use case". I know
you want strict typing. I even proposed the option for it. But if you
read "function bar(int $num)" in the PHP manual, coercive typing is
exactly what it means. That's how it has been since forever.
It has nothing to do with arrays, because - repeating it in like 10000th
time in this discussion - arrays are not scalars and PHP does not coerce
non-scalars, only scalars. You can make scalars work like non-scalars -
that would mean turning PHP into strongly typed language, like Python.
Stas Malyshev
smalyshev@gmail.com
That's how all internal functions work. It looks like you didn't
actually read my argument but just repeated "I want my use case".
Sorry, I read all you said and understood it perfectly.
I know you want strict typing. I even proposed the option for it.
No, you're wrong. I NEVER EVER said we should have "strict typing" in
detriment of coercive types simply because there is no general
consensus about what "strict" means :)
But I also don't want to have coercive type hints to occupy the best
"syntax slot" that could be used for more strict type checks
in the future, being "strict" a negotiable term that deserves more
debate. I'm just claiming that (int) $num
is more explicit, has no
BC breaks and should, IMMO, be the preferred choice.
You can disagree with that, of course, but don't quote "I want my use
case" as being something I said, wished or even though.
But if you read "function bar(int $num)" in the PHP manual, coercive typing is
exactly what it means. That's how it has been since forever.
Sorry, but this is the syntax used by the manual to describe functions
usage, not the actual implementation. The manual can be updated. The
implementation itself can't be changed after major version release.
2015-01-15 21:54 GMT-03:00 Stanislav Malyshev smalyshev@gmail.com:
Hi!
The hole point (at least for me) for being against
function bar(int $num){}
to achieve type coercion is that the syntactic equivalent
codefunction bar(array $numbers){}
won't do any coercion - (array)
$numbers - because BC break would be too big to handle.Having
int|integer|bool|float|real|string
as coercive type hints
whilearray
is "strict" looks like an ugly hack (no pun intended).That's how all internal functions work. It looks like you didn't
actually read my argument but just repeated "I want my use case". I know
you want strict typing. I even proposed the option for it. But if you
read "function bar(int $num)" in the PHP manual, coercive typing is
exactly what it means. That's how it has been since forever.It has nothing to do with arrays, because - repeating it in like 10000th
time in this discussion - arrays are not scalars and PHP does not coerce
non-scalars, only scalars. You can make scalars work like non-scalars -
that would mean turning PHP into strongly typed language, like Python.Stas Malyshev
smalyshev@gmail.com
Hi!
detriment of coercive types simply because there is no general
consensus about what "strict" means :)
I don't see any place for "consensus" and "non-consensus" here - unless
you want to redefine words to have arbitrary meanings so nobody
understands you, it is pretty clear what "strict" means - typing system
in which the variable marked with certain type accepts only value of
that type and nothing else. What other definition could you have in mind?
But I also don't want to have coercive type hints to occupy the best
"syntax slot" that could be used for more strict type checks
That's fine that you want your use case to be most convenient for you,
unfortunately that place has been already taken for years.
debate. I'm just claiming that
(int) $num
is more explicit, has no
BC breaks and should, IMMO, be the preferred choice.
No, it should not be, and I just wrote two mails explaining why exactly
it should not. Here's the third.
Sorry, but this is the syntax used by the manual to describe functions
usage, not the actual implementation. The manual can be updated. The
Of course, we can rewrite the whole manual and the whole language. The
question is - why we should make such huge changes if we already have
this meaning and it has been there for years and it always meant exactly
that - coercive typing for scalars - and never meant anything else?
implementation itself can't be changed after major version release.
The manual is what people read and rely on. But there's a bigger issue
that you keep ignoring - that the functions having scalar typed argument
are coercive right now. You describe it as if it's a typo in the
manual that can be fixed or something that happened by accident and
nobody intended it. Nothing can be further from the truth - it's how
weak typing has been always working in PHP. You want new feature for
your use case? Fine, but claiming existing syntax for it and saying "no
problem we'd just rewrite the whole manual and disregard 20 years of PHP
history" sounds like a bit too much to ask.
--
Stas Malyshev
smalyshev@gmail.com
Stanislav Malyshev,
detriment of coercive types simply because there is no general
consensus about what "strict" means :)I don't see any place for "consensus" and "non-consensus" here -
unless you want to redefine words to have arbitrary meanings so nobody
understands you, it is pretty clear what "strict" means
People have been using the term "strict" with clearly different
meanings over the threads.
For some it means total strictness, for others just between numbers vs
strings, for others it means that coercion should
occur only when there is no data loss and there are many other meanings.
Even Nikic presented different versions of "strict" proposals on an
old article > http://nikic.github.io/2012/03/06/Scalar-type-hinting-is-harder-than-you-think.html
That's why I said the meaning of a "strict" implementation hasn't
reach consensus but you tried pretty hard to do not understand it.
Citation again:
I don't see any place for "consensus" and "non-consensus" here -
unless you want to redefine words to have arbitrary meanings so nobody
understands you [...]
You're basically stretching my words, trying to make it look mean in
some way (stop that ;)
Now I understand why folks rage quit internals once in a while...
PS: I'm out this thread, but hope the POV about the language feature
was clear enough to the objective debate.
2015-01-15 22:41 GMT-03:00 Stanislav Malyshev smalyshev@gmail.com:
Hi!
detriment of coercive types simply because there is no general
consensus about what "strict" means :)I don't see any place for "consensus" and "non-consensus" here - unless
you want to redefine words to have arbitrary meanings so nobody
understands you, it is pretty clear what "strict" means - typing system
in which the variable marked with certain type accepts only value of
that type and nothing else. What other definition could you have in mind?But I also don't want to have coercive type hints to occupy the best
"syntax slot" that could be used for more strict type checksThat's fine that you want your use case to be most convenient for you,
unfortunately that place has been already taken for years.debate. I'm just claiming that
(int) $num
is more explicit, has no
BC breaks and should, IMMO, be the preferred choice.No, it should not be, and I just wrote two mails explaining why exactly
it should not. Here's the third.Sorry, but this is the syntax used by the manual to describe functions
usage, not the actual implementation. The manual can be updated. TheOf course, we can rewrite the whole manual and the whole language. The
question is - why we should make such huge changes if we already have
this meaning and it has been there for years and it always meant exactly
that - coercive typing for scalars - and never meant anything else?implementation itself can't be changed after major version release.
The manual is what people read and rely on. But there's a bigger issue
that you keep ignoring - that the functions having scalar typed argument
are coercive right now. You describe it as if it's a typo in the
manual that can be fixed or something that happened by accident and
nobody intended it. Nothing can be further from the truth - it's how
weak typing has been always working in PHP. You want new feature for
your use case? Fine, but claiming existing syntax for it and saying "no
problem we'd just rewrite the whole manual and disregard 20 years of PHP
history" sounds like a bit too much to ask.--
Stas Malyshev
smalyshev@gmail.com
Hi!
Even Nikic presented different versions of "strict" proposals on an
old article > http://nikic.github.io/2012/03/06/Scalar-type-hinting-is-harder-than-you-think.html
I don't see "different versions" - I see one version of "strict" which
matches my description and which he unequivocally opposes. What he
supports is "weak type hints, but with stricter input validation". Which
is not what the proposed RFC is calling "strict" - "With this approach,
an argument is only accepted if its type is exactly the same as the
parameter." - which again exactly the same as I said. So in this regard,
myself, Andrea and Nikita are in full agreement about what "strict"
means, however much we disagree in other aspects.
--
Stas Malyshev
smalyshev@gmail.com
debate. I'm just claiming that
(int) $num
is more explicit, has no
BC breaks and should, IMMO, be the preferred choice.No, it should not be, and I just wrote two mails explaining why exactly
it should not. Here's the third.Sorry, but this is the syntax used by the manual to describe
functions
usage, not the actual implementation. The manual can be updated. TheOf course, we can rewrite the whole manual and the whole language.
You're muddling two things here: changing the notation in the manual would require absolutely no changes to the language, as long as it used a self-consistent notation to describe the language's behaviour.
The
question is - why we should make such huge changes if we already have
this meaning and it has been there for years and it always meant
exactly
that - coercive typing for scalars - and never meant anything else?
Those reasons have been given many times; in summary, to keep the syntax for coercive hints distinct from the syntax for strict hints, rather than the same syntax meaning one for scalars and the other for non-scalars.
implementation itself can't be changed after major version release.
The manual is what people read and rely on. But there's a bigger issue
that you keep ignoring - that the functions having scalar typed
argument
are coercive right now. You describe it as if it's a typo in the
manual that can be fixed or something that happened by accident and
nobody intended it. Nothing can be further from the truth - it's how
weak typing has been always working in PHP.
Now you are talking about the existence of the feature, not the syntax. It's a good argument for including coercive typing if any type hints are added, but internal functions will not need to be changed based on userland syntax.
You want new feature for
your use case? Fine, but claiming existing syntax for it and saying "no
problem we'd just rewrite the whole manual and disregard 20 years of
PHP
history" sounds like a bit too much to ask.
There is no existing syntax in the language for scalar type hints of any kind.
As for the manual, IIRC, there's already precedent for altering its conventions to match language features, when "callable" was introduced as a typehint; the manual previously used "callback" to annotate those parameters.
The manual also uses return type on the left, but I don't think anyone's arguing that decides the discussion on that syntax, which will probably actually put return types on the right.
It's just a convention in the manual which doesn't actually match any existing PHP code, and can be changed with no compatibility issues whatsoever.
Regards,
Rowan Collins
[IMSoP]
Hi!
I’m not really sure this is true. I agree that strict types aren’t
entirely in keeping with the “PHP way”. However, there are plenty of
people who are against them not for that reason, but simply because
they don’t work well for them. Plus, I’m not sure strict typing
I would say for myself it is both. Having PHP code that thinks 1 can not
be used as boolean true just feels wrong philosophically, but on top of
that I imaging how much (type) conversions I'd have to use to deal with
strictly-typed code in practice - it makes me sad for practical reasons.
weakly-typed. Indeed, strict type hints don’t stop PHP being
weakly-typed. They just check types at function call boundaries.
"Strict types don't stop PHP being weakly typed". No, that doesn't work.
Adding misleading word "hints" doesn't help either. What happens is that
with this proposal PHP would be partly strictly typed and partly weakly
typed. Which would be subject of both confusion and criticism about
language not being consistent - in one context it's fine to use 1 as
boolean, in another it's not, the fun is in the remembering where is which.
This is unlikely to be super-representative of the PHP community.
It's not even representative of the list, that's why we have votes :)
Claiming vote result pre-vote seems to be not very useful.
Except that is not the case for this proposal, which explicitly and
deliberately prevents the directive affecting inclusion. The
behaviour is impossible to toggle at runtime, unless you’re using
some weird extension which lets you edit the flag on the
ZEND_DO_FCALL opcode.
ZEND_DO_FCALL is not by far the only way to call a function. There are
many other ways. Keeping them all in sync and tracking the proper
context for each of them would be a very fun exercise. That's why
state-dependent behaviors usually aren't a good idea, especially if
state happens in one place and behavior in another.
Stas Malyshev
smalyshev@gmail.com
Hello Andrea,
Hi Zeev,
Andrea,
I'm not sure what you're basing that assumption on. The incidental
interactions you (or anybody) may have with 'the community', by no way
represent the opinion of the community at large. The vast majority of
the
PHP community never ever interacts with internals@, never attend
conferences, don't write blog posts about PHP and are generally
completely
'under the radar'. I would actually go to argue that the people who do
attend conferences, participate on internals@ or write blog posts - are
not
representative of the PHP userbase at large. The vast majority of
developers I bump into - you will never ever hear from. They constitute
the
vast majority of the ~5M strong PHP developer base.So even though my belief / educated guess is that the vast majority of
the
PHP userbase would prefer to see strict typing kept off this language,
I'm
not going to argue that - but we must not argue the opposite either,
based
on the non-representative anecdotal data from a few dozen people.Whether or not they are in the majority, a very large portion of PHP
developers would prefer strict typing. In particular, the most vocal ones
would seem to. There are also a lot of PHP developers who would prefer weak
typing. Thus we have a problem: either approach to scalar hints will upset
a large portion of the community.
I actually quite disagree with that statement. Both as a library/framework
developer and a user land developer I find strict typing to be more of an
issue. For instance:
function foo(int $foo)
foo('23');
This would be a pain and cause constant glue from userland:
Option A: Force Cast aka (int) '23'
Option B: Check for digits via ctype_digits then force cast
etc.
To provide more of a point here, variables coming from HTTP are always a
string, this makes strict casting a troubling item, considering that the
main way of fetching input is coming from the web specifically. I'm
certain this would also affect other areas as well such as reading csv
files and more. To me this point alone makes a vastly strong statement
against strict typing and as such, it would make life far more difficult
for library developers and user land developers alike.
Myself, I might have been somewhat happy with just weak hints, but
it would upset an awful lot of developers who would like some measure of
strict typing. Developers who would most likely not use the new scalar
type
hints, because they weren’t strict. And if nobody uses them, why add
them?How do you deduce that 'nobody uses them' from the fact that some group
of
people said they won't? I'm sorry, but it makes no sense, especially
given
the positive feedback you saw on internals, making it clear that there
would
be in fact people using it.Not all of it was positive. Sure, a lot of people would use them though,
but I’ve heard quite a few developers say they wouldn’t use them and
continue to use manual (!is_int($foo))-style assertions.If there's one thing that's worse than introducing an alien concept like
strict typing into PHP, it's introducing it as a feature that will
include
all the negatives of this alien concept, PLUS have the ability to
radically
change how it behaves based on a runtime option.This isn’t a runtime option, it is entirely compile-time. Much like
namespaces are not a runtime option. There isn’t even the ability to toggle
it at runtime, unless we somehow add some ability to edit the flags on
individual opcodes.
I agree with the others in that declarative syntax to change it is a bad
idea. It actually reminds me of ECMAScript 5's "use strict" (
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)
condition. Changing the definition based on user land scripts can lead to
bugs and inconsistencies in a library developers purpose of a package and
cause bad conditions. It also means that then a library developer would
need to handle conditions on both sides (when in weak vs. strict). So I
don't really understand where the gains of this would come from and it
actually causes me concern in that what if a developer forgets to define
strict and you're entire system is built on strict.
Regards,
Mike
Hello Mike,
I actually quite disagree with that statement.
I don’t understand. I said "either approach to scalar hints will upset a large portion of the community”. Are you not demonstrating that point, in that you don’t like the strict approach?
Both as a library/framework developer and a user land developer I find strict typing to be more of an issue. For instance:
function foo(int $foo)
foo('23');This would be a pain and cause constant glue from userland:
Option A: Force Cast aka (int) '23'
Option B: Check for digits via ctype_digits then force cast
etc.To provide more of a point here, variables coming from HTTP are always a string, this makes strict casting a troubling item, considering that the main way of fetching input is coming from the web specifically. I'm certain this would also affect other areas as well such as reading csv files and more. To me this point alone makes a vastly strong statement against strict typing and as such, it would make life far more difficult for library developers and user land developers alike.
Well, this RFC doesn’t force you to use strict type checking. Quite the opposite.
I agree with the others in that declarative syntax to change it is a bad idea. It actually reminds me of ECMAScript 5's "use strict" (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode) condition. Changing the definition based on user land scripts can lead to bugs and inconsistencies in a library developers purpose of a package and cause bad conditions. It also means that then a library developer would need to handle conditions on both sides (when in weak vs. strict).
No, the library developer would never need to “handle both cases”. Your library always gets the type it asks for. The RFC is quite clear on this. Your code will always behave exactly the same.
Thanks.
--
Andrea Faulds
http://ajf.me/
Hi Andrea,
I actually quite disagree with that statement.
I don’t understand. I said "either approach to scalar hints will upset a
large portion of the community”. Are you not demonstrating that point, in
that you don’t like the strict approach?
Sure, I am demonstrating that a bit, but I am of the opinion that either
will work but not both. Whilst I prefer weak, I would take strict as well
to have "something". Having both would be a very strange inconsistency.
Sorry for not being more clear. I would not be upset in either condition
but I certainly lead toward a certain direction.
Both as a library/framework developer and a user land developer I find
strict typing to be more of an issue. For instance:function foo(int $foo)
foo('23');This would be a pain and cause constant glue from userland:
Option A: Force Cast aka (int) '23'
Option B: Check for digits via ctype_digits then force cast
etc.To provide more of a point here, variables coming from HTTP are always a
string, this makes strict casting a troubling item, considering that the
main way of fetching input is coming from the web specifically. I'm
certain this would also affect other areas as well such as reading csv
files and more. To me this point alone makes a vastly strong statement
against strict typing and as such, it would make life far more difficult
for library developers and user land developers alike.Well, this RFC doesn’t force you to use strict type checking. Quite the
opposite.I agree with the others in that declarative syntax to change it is a bad
idea. It actually reminds me of ECMAScript 5's "use strict" (
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)
condition. Changing the definition based on user land scripts can lead to
bugs and inconsistencies in a library developers purpose of a package and
cause bad conditions. It also means that then a library developer would
need to handle conditions on both sides (when in weak vs. strict).No, the library developer would never need to “handle both cases”. Your
library always gets the type it asks for. The RFC is quite clear on this.
Your code will always behave exactly the same.
I may not have described this clearly. If I make a library with a method
that states an int, the declarative syntax now makes me have to take both
due to your earlier comment on that userland would define the condition.
This means that if I declared handling inside my library to be strict but
the caller was in weak, I would need to handle that condition. Now from
that perspective I cannot rely that I am in strict and would have to handle
the default weak even although I declared in my class that i wanted strict
mode which only affected the code inside of that file. That's ultimately
what I am saying and why I am stating it would have to handle both
conditions. In reality, you'd always act as if you were in a weak mode
supporting that case.
Hi Mike,
I may not have described this clearly. If I make a library with a method that states an int, the declarative syntax now makes me have to take both due to your earlier comment on that userland would define the condition. This means that if I declared handling inside my library to be strict but the caller was in weak, I would need to handle that condition.
How, exactly, would you need to handle that condition? You don’t need to do anything yourself.
As the RFC itself says:
In both approaches, the function will always get exactly the argument type it asks for. In the case of strict type-checking, this is done by rejecting incorrectly-typed values. In the case of weak type-checking, this is done by rejecting some values, and converting others. Therefore, the following code will always work, regardless of mode:
function foobar(int $i) { if (!is_int($i)) { throw new Exception("Not an integer."); // this will never happen } }
No matter whether foobar() is called from strictly type-checked or weakly type-checked code, the $i argument you get will always, without fail, be an integer. Thus, I do not see how you "would need to handle that condition”.
Now from that perspective I cannot rely that I am in strict and would have to handle the default weak even although I declared in my class that i wanted strict mode which only affected the code inside of that file. That's ultimately what I am saying and why I am stating it would have to handle both conditions. In reality, you'd always act as if you were in a weak mode supporting that case.
I… really don’t understand, I’m sorry. Are you complaining that if a caller uses the weak mode, they are not bound by strict types? Why do you want to affect the code of the caller?
--
Andrea Faulds
http://ajf.me/
Hi,
Now from that perspective I cannot rely that I am in strict and would have to handle the default weak even although I declared in my class that i wanted strict mode which only affected the code inside of that file. That's ultimately what I am saying and why I am stating it would have to handle both conditions. In reality, you'd always act as if you were in a weak mode supporting that case.
I… really don’t understand, I’m sorry. Are you complaining that if a caller uses the weak mode, they are not bound by strict types? Why do you want to affect the code of the caller?
Consider this badly designed API:
declare(strict_typehints=TRUE);
const MODE_APPEND = 0;
const MODE_TRUNCATE = 1;
const MODE_PREPEND = 2;
function write_file(string $path, int $mode, string $data)
{
// it's quite obvious
}
Somewhere else, you forget the parameters order ...
declare(strict_typehints=FALSE);
$path = '/important/file.dat';
$data = '1 year';
$mode = MODE_APPEND;
write_file($path, $data, $mode);
It's a bad example - an awful (and indeed, very much useless) API,
combined with an absent-minded consumer. Yet, it demonstrates how
putting the caller in control can cause a disaster.
Of course, it is fair to say that this would be a very rare case,
where it is the author's fault for both being bad at design and
relying on a type-hinting feature that they don't understand, but it
is also fair to say that it is possible that a lot of people assume
that "strict_typehint=TRUE" affects definitions instead of calls (I
know I would, if I wasn't following this list).
But anyway, the point is - if you can't rely on it, why use it at all?
I guess if your goal was to use strict typing as a debugging tool
here, it makes some sense, but otherwise the way it works is
completely inverted.
What I would suggest is the '(type) $weak' vs 'type $strict' syntax
that was already mentioned.
I've said this before, during the previous RFCs discussions - all of
these proposals will fail, because they all suggest using the 'type
$whatever' syntax and that automatically upsets the "other camp",
whichever it is, but especially if the "other camp" is supporters of
strict typing. That's the moment when they become opposition, while
they could've otherwise not care because it's simply not their
"battle". If both are proposed to co-exist in a clean way (instead of
via a switch), I believe that we'll get substantially more positive
opinions from both sides.
And to hell with the "consistency" argument. Since when did PHP become
that concerned about purity and high consistency levels? Call this a
speculation, but barely a few people care for the the internal
functions' behavior - most of us will be happy if they stay as is
regardless of the kind of type-hinting that gets adopted. What we want
is the features (plural!), not the philosophy.
Cheers,
Andrey.
Hi Andrey,
Consider this badly designed API:
declare(strict_typehints=TRUE);
const MODE_APPEND = 0;
const MODE_TRUNCATE = 1;
const MODE_PREPEND = 2;function write_file(string $path, int $mode, string $data)
{
// it's quite obvious
}Somewhere else, you forget the parameters order ...
declare(strict_typehints=FALSE);
$path = '/important/file.dat';
$data = '1 year';
$mode = MODE_APPEND;write_file($path, $data, $mode);
It's a bad example - an awful (and indeed, very much useless) API,
combined with an absent-minded consumer. Yet, it demonstrates how
putting the caller in control can cause a disaster.
Sure, weak typing is much poorer than strict typing for error checking. Does that mean the user should be prevented from having the choice?
Are you simply opposed to the idea of weak types in general?
What I would suggest is the '(type) $weak' vs 'type $strict' syntax
that was already mentioned.I've said this before, during the previous RFCs discussions - all of
these proposals will fail, because they all suggest using the 'type
$whatever' syntax and that automatically upsets the "other camp",
whichever it is, but especially if the "other camp" is supporters of
strict typing. That's the moment when they become opposition, while
they could've otherwise not care because it's simply not their
"battle". If both are proposed to co-exist in a clean way (instead of
via a switch), I believe that we'll get substantially more positive
opinions from both sides.
Both co-existing doesn’t solve anything, if anything it makes it worse.
People who like weak typing don’t want to have to use APIs with strict type hints. If you’re like Zeev and believe it is fundamentally at odds with PHP, you’ll especially dislike it.
People who like strict typing don’t want to have to use APIs with weak type hints.
And to hell with the "consistency" argument. Since when did PHP become
that concerned about purity and high consistency levels?
I don’t care if PHP is concerned about it. I am concerned about the mess caused by having two or three different argument type checking modes being used within the same function.
Marco and S.A.N.:
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?This idea has been so recurrent and yet systematically ignored by RFC owners. Why? I think that we need to baby step and try to approve coercive type declarations first and decide upon a possible stricter type check later:
How a bout a reboot of what ircmaxell@php.net already started in https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?
PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea then v0.1 instantly becomes more acceptable", we still have time to try some alternatives.
See what I said above to Andreey.
This RFC doesn’t ignore having two syntaxes. It sets out to avoid the nightmare that two syntaxes would cause.
Thanks.
--
Andrea Faulds
http://ajf.me/
Sure, weak typing is much poorer than strict typing for error checking. Does that mean the user should be prevented from having the choice?
Are you simply opposed to the idea of weak types in general?
Another way to put this:
Allow a user to shoot themselves in the foot (use weak types) if they want. Don’t force me to shoot myself in the foot if I don’t want to (give APIs the choice of weak typing, not the user).
--
Andrea Faulds
http://ajf.me/
What about doing both weak and strict with two different syntaxes?
public function __construct(string $name, $age as int, $cuteness as float, bool $evil) {
string $name // strict
$age as int // weak
$cuteness as float // weak
bool $evil // strict
"as" Syntax is taken from SQL92.
Regards
Thomas
Andrea Faulds wrote on 15.01.2015 20:52:
Hi Andrey,
Consider this badly designed API:
declare(strict_typehints=TRUE);
const MODE_APPEND = 0;
const MODE_TRUNCATE = 1;
const MODE_PREPEND = 2;function write_file(string $path, int $mode, string $data)
{
// it's quite obvious
}Somewhere else, you forget the parameters order ...
declare(strict_typehints=FALSE);
$path = '/important/file.dat';
$data = '1 year';
$mode = MODE_APPEND;write_file($path, $data, $mode);
It's a bad example - an awful (and indeed, very much useless) API,
combined with an absent-minded consumer. Yet, it demonstrates how
putting the caller in control can cause a disaster.Sure, weak typing is much poorer than strict typing for error checking. Does
that mean the user should be prevented from having the choice?Are you simply opposed to the idea of weak types in general?
What I would suggest is the '(type) $weak' vs 'type $strict' syntax
that was already mentioned.I've said this before, during the previous RFCs discussions - all of
these proposals will fail, because they all suggest using the 'type
$whatever' syntax and that automatically upsets the "other camp",
whichever it is, but especially if the "other camp" is supporters of
strict typing. That's the moment when they become opposition, while
they could've otherwise not care because it's simply not their
"battle". If both are proposed to co-exist in a clean way (instead of
via a switch), I believe that we'll get substantially more positive
opinions from both sides.Both co-existing doesn’t solve anything, if anything it makes it worse.
People who like weak typing don’t want to have to use APIs with strict type
hints. If you’re like Zeev and believe it is fundamentally at odds with PHP,
you’ll especially dislike it.People who like strict typing don’t want to have to use APIs with weak type
hints.And to hell with the "consistency" argument. Since when did PHP become
that concerned about purity and high consistency levels?I don’t care if PHP is concerned about it. I am concerned about the mess
caused by having two or three different argument type checking modes being used
within the same function.Marco and S.A.N.:
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?This idea has been so recurrent and yet systematically ignored by RFC
owners. Why? I think that we need to baby step and try to approve coercive
type declarations first and decide upon a possible stricter type check later:How a bout a reboot of what ircmaxell@php.net already started in
https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea
then v0.1 instantly becomes more acceptable", we still have time to try some
alternatives.See what I said above to Andreey.
This RFC doesn’t ignore having two syntaxes. It sets out to avoid the
nightmare that two syntaxes would cause.Thanks.
--
Andrea Faulds
http://ajf.me/
For me personally, I would use strict hints for private/protected methods and weak hints for public methods.
Regards
Thomas
Thomas Bley wrote on 15.01.2015 21:16:
What about doing both weak and strict with two different syntaxes?
public function __construct(string $name, $age as int, $cuteness as float, bool
$evil) {string $name // strict
$age as int // weak
$cuteness as float // weak
bool $evil // strict"as" Syntax is taken from SQL92.
Regards
ThomasAndrea Faulds wrote on 15.01.2015 20:52:
Hi Andrey,
Consider this badly designed API:
declare(strict_typehints=TRUE);
const MODE_APPEND = 0;
const MODE_TRUNCATE = 1;
const MODE_PREPEND = 2;function write_file(string $path, int $mode, string $data)
{
// it's quite obvious
}Somewhere else, you forget the parameters order ...
declare(strict_typehints=FALSE);
$path = '/important/file.dat';
$data = '1 year';
$mode = MODE_APPEND;write_file($path, $data, $mode);
It's a bad example - an awful (and indeed, very much useless) API,
combined with an absent-minded consumer. Yet, it demonstrates how
putting the caller in control can cause a disaster.Sure, weak typing is much poorer than strict typing for error checking. Does
that mean the user should be prevented from having the choice?Are you simply opposed to the idea of weak types in general?
What I would suggest is the '(type) $weak' vs 'type $strict' syntax
that was already mentioned.I've said this before, during the previous RFCs discussions - all of
these proposals will fail, because they all suggest using the 'type
$whatever' syntax and that automatically upsets the "other camp",
whichever it is, but especially if the "other camp" is supporters of
strict typing. That's the moment when they become opposition, while
they could've otherwise not care because it's simply not their
"battle". If both are proposed to co-exist in a clean way (instead of
via a switch), I believe that we'll get substantially more positive
opinions from both sides.Both co-existing doesn’t solve anything, if anything it makes it worse.
People who like weak typing don’t want to have to use APIs with strict type
hints. If you’re like Zeev and believe it is fundamentally at odds with PHP,
you’ll especially dislike it.People who like strict typing don’t want to have to use APIs with weak type
hints.And to hell with the "consistency" argument. Since when did PHP become
that concerned about purity and high consistency levels?I don’t care if PHP is concerned about it. I am concerned about the mess
caused by having two or three different argument type checking modes being
used
within the same function.Marco and S.A.N.:
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?This idea has been so recurrent and yet systematically ignored by RFC
owners. Why? I think that we need to baby step and try to approve coercive
type declarations first and decide upon a possible stricter type check later:How a bout a reboot of what ircmaxell@php.net already started in
https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea
then v0.1 instantly becomes more acceptable", we still have time to try some
alternatives.See what I said above to Andreey.
This RFC doesn’t ignore having two syntaxes. It sets out to avoid the
nightmare that two syntaxes would cause.Thanks.
--
Andrea Faulds
http://ajf.me/
The main advantage of the two syntaxes:
-
Strict
function bar(int $num){} -
Weak
function bar((int) $num){}
Any junior-middle PHP developer, seeing this syntax in the code can
understand how it works, without studying the documentation and without
your complex conversion tables.
Explicit is better than implicit, is the motto Python, here it is very
relevant.
S.A.N,
The main advantage of the two syntaxes:
Strict
function bar(int $num){}Weak
function bar((int) $num){}Any junior-middle PHP developer, seeing this syntax in the code can
understand how it works, without studying the documentation and without
your complex conversion tables.Explicit is better than implicit, is the motto Python, here it is very
relevant.
Just listing the advantages of the withdrawn ircmaxwell's RFC
https://wiki.php.net/rfc/parameter_type_casting_hints over this one (both
v0.1 and v0.2):
- No BC breaks (classes named int, float, string would not become reserved)
- More semantic and explicit (just like S.A.N said)
- Will not block possible strict typing RFCs to get voted in the future
- No reserved words added
- Minimalist implementation (no runtime flags, configurations, etc)
I'm not trying to highjack the topic here... just adding an alternative to
an RFC that seems to become more and more polemic with both sides
unsatisfied :)
I don't think any junior-middle php developer with understand how "(int)"
works.
Just make a test and see how many will answer (int)'asd' with 1.
Thomas,
Actually (int)'asd'
would be evaluated to 0 ;) ... (int)'1asd'
would be
evaluated to 1, though (I guess that's what you tried to say?).
2015-01-15 18:18 GMT-03:00 S.A.N ua.san.alex@gmail.com:
The main advantage of the two syntaxes:
Strict
function bar(int $num){}Weak
function bar((int) $num){}Any junior-middle PHP developer, seeing this syntax in the code can
understand how it works, without studying the documentation and without
your complex conversion tables.Explicit is better than implicit, is the motto Python, here it is very
relevant.
What about doing both weak and strict with two different syntaxes?
public function __construct(string $name, $age as int, $cuteness as
float, bool $evil) {string $name // strict
$age as int // weak
$cuteness as float // weak
bool $evil // strict"as" Syntax is taken from SQL92.
Regards
Thomas
This is what some are proposing, but with slightly different syntax choices, inspired by existing cast operators:
public function __construct(string $name, (int) $age, (float) $cuteness, bool $evil)
Like literally every proposal in this area, some people think it's The Solution, others absolutely hate it.
Andrea has stated (if I'm not paraphrasing too badly) that a major reason for putting the caller in control, not the definer, is that it's easier to reason about code where all the calls you are looking at follow one behaviour, regardless of where they were defined.
I think the problem with the current rfc is:
test(42);
function test(string $a) does test((string)$a);
function test(array $a) does not test((array)$a); although casting would be possible.
So for consistency we might change the syntax or adapt array/object type hints with casting (BC-break).
Regards
Thomas
Rowan Collins wrote on 15.01.2015 23:09:
What about doing both weak and strict with two different syntaxes?
public function __construct(string $name, $age as int, $cuteness as
float, bool $evil) {string $name // strict
$age as int // weak
$cuteness as float // weak
bool $evil // strict"as" Syntax is taken from SQL92.
Regards
ThomasThis is what some are proposing, but with slightly different syntax choices,
inspired by existing cast operators:public function __construct(string $name, (int) $age, (float) $cuteness, bool
$evil)Like literally every proposal in this area, some people think it's The
Solution, others absolutely hate it.Andrea has stated (if I'm not paraphrasing too badly) that a major reason for
putting the caller in control, not the definer, is that it's easier to reason
about code where all the calls you are looking at follow one behaviour,
regardless of where they were defined.
Hi Thomas,
I think the problem with the current rfc is:
test(42);
function test(string $a) does test((string)$a);
function test(array $a) does not test((array)$a); although casting would be possible.So for consistency we might change the syntax or adapt array/object type hints with casting (BC-break).
Having it do an explicit cast would make the feature really dangerous. Explicit casts can’t fail (except for objects, for whatever reason) and so they’ll completely mangle input if it’s bad. Implicit casts can fail.
I don’t think this would be a good approach.
Thanks.
Andrea Faulds
http://ajf.me/
Hi Andrea,
Sure, weak typing is much poorer than strict typing for error checking. Does that mean the user should be prevented from having the choice?
Are you simply opposed to the idea of weak types in general?
I am opposed to the idea of having only weak types, or that there's
one way to rule them all.
And you might argue that this RFC provides both, but it obviously only
appears to do so in practice.
Both co-existing doesn’t solve anything, if anything it makes it worse.
People who like weak typing don’t want to have to use APIs with strict type hints. If you’re like Zeev and believe it is fundamentally at odds with PHP, you’ll especially dislike it.
People who like strict typing don’t want to have to use APIs with weak type hints.
... and this is where we fundamentally disagree.
I like both, I want to use both for different use cases and I don't
see what is it that will be bad about co-existence.
Any library author who wants strictness will force it on you, even
if that means writing 3x times more code.
I don’t care if PHP is concerned about it. I am concerned about the mess caused by having two or three different argument type checking modes being used within the same function.
And yes, I also want to use both weak and strict type-hints in the
same function. :)
Hi,
I would like to call everyone's attention, specially people
contributing directly to this RFC series, to what S.A.N just said:Many developers PHP offers dual syntax:
Strict
function bar(int $num){}Lax
function bar((int) $num){}Maybe it makes sense to put this option on the ballot if it passes a vote,
it will be possible to put an end to the discus?This idea has been so recurrent and yet systematically ignored by RFC owners. Why? I think that we need to baby step and try to approve coercive type declarations first and decide upon a possible stricter type check later:
How a bout a reboot of what ircmaxell@php.net already started in https://wiki.php.net/rfc/parameter_type_casting_hints for v0.3?
PS: Please, let's not fall into the mindset of "if v0.2 is not a good idea then v0.1 instantly becomes more acceptable", we still have time to try some alternatives.
I almost completely agree, especially with the postscript (but
excluding the baby steps, although ... it's a good price to pay if we
all end up happy).
I believe the linked RFC was withdrawn because that's when Anthony
Ferrara "rage" quit internals? My money would be on it being accepted
and already running in the wild if that hadn't happened. There's no
reason not to.
Cheers,
Andrey.
Andrey Andreev wrote:
I like both, I want to use both for different use cases and I don't
see what is it that will be bad about co-existence.
Any library author who wants strictness will force it on you, even
if that means writing 3x times more code.
Why would a library author want such strictness?
--
Christoph M. Becker
Hi,
Now from that perspective I cannot rely that I am in strict and
would have to handle the default weak even although I declared in my
class that i wanted strict mode which only affected the code inside of
that file. That's ultimately what I am saying and why I am stating it
would have to handle both conditions. In reality, you'd always act as
if you were in a weak mode supporting that case.I… really don’t understand, I’m sorry. Are you complaining that if a
caller uses the weak mode, they are not bound by strict types? Why do
you want to affect the code of the caller?Consider this badly designed API:
declare(strict_typehints=TRUE);
const MODE_APPEND = 0;
const MODE_TRUNCATE = 1;
const MODE_PREPEND = 2;function write_file(string $path, int $mode, string $data)
{
// it's quite obvious
}Somewhere else, you forget the parameters order ...
declare(strict_typehints=FALSE);
$path = '/important/file.dat';
$data = '1 year';
$mode = MODE_APPEND;write_file($path, $data, $mode);
It's a bad example - an awful (and indeed, very much useless) API,
combined with an absent-minded consumer. Yet, it demonstrates how
putting the caller in control can cause a disaster.
But, crucially, it causes a disaster for the caller. The library function gets exactly the types it expects, and can happily pass them to some other typehinted function, including an internal/extension function.
The "disaster" is that the effect is not what the caller intended, which would be true for all sorts of other mistakes. No amount of strict type hinting will solve my inability to remember whether strpos()
takes haystack, needle or needle, haystack.
Presented with a function typehinted as foo(int $a), the same people who'd write code in "weak mode" under the current proposal would probably just change foo($_GET['id']) to foo((int) $_GET['id']), with exactly the same effect. There is absolutely nothing the author of foo() can do to stop them, no matter what options we give at the definition site.
The sheer difficulty people are having understanding the "caller is in control" concept probably counts as its biggest flaw, though...
--
Rowan Collins
[IMSoP]
Hi!
And to hell with the "consistency" argument. Since when did PHP become
that concerned about purity and high consistency levels? Call this a
The "purity" part should be addressed to strict proponents - it's their
purist sensibilities that are offended by converting '23' to 23 ;) As
for concern with high consistency - when you have 5M users, you have to
grow up a bit. We used to commit features when we feel like it, release
when it rained on Thursday and our RFC process was "nobody screamed for
a month after I committed it so it's probably OK". Now we have RFC
process, release schedule, CI, votes and nobody seems to be worse off
because of that. We can have more consistency in the language too, and
we won't feel worse because of it either - in fact, we'll be better.
speculation, but barely a few people care for the the internal
functions' behavior - most of us will be happy if they stay as is
regardless of the kind of type-hinting that gets adopted. What we want
is the features (plural!), not the philosophy.
Actually, we want both. Language is not just a bag of tricks, at least a
good one. It's also an underlying philosophy which allows you to
understand why these tricks work the way they do and how to use them in
most efficient manner. If the tricks are just random, it conflicts with
the pattern-matching nature of human brain and makes it harder to use
it. That's why people see faces on Mars and rabbits on the Moon - people
need patterns they can recognize. If you don't give them the good
patterns, it makes harder to work with the thing.
--
Stas Malyshev
smalyshev@gmail.com
Mike Willbanks wrote on 15/01/2015 16:55:
It also means that then a library developer would
need to handle conditions on both sides (when in weak vs. strict). So I
don't really understand where the gains of this would come from and it
actually causes me concern in that what if a developer forgets to define
strict and you're entire system is built on strict.
In case this hasn't been repeated enough times already: No They Would Not.
As a library developer, you do not rely on strict or weak hints, you
rely on the variables you receive being of the types you require. This
is guaranteed in both modes.
You cannot stop the user of your library doing whatever it takes to get
past your validation. It is up to them to provide sane inputs to your
published API, and no version of type hinting can change that.
Regards,
Rowan Collins
[IMSoP]
Hi,
Mike Willbanks wrote on 15/01/2015 16:55:
It also means that then a library developer would
need to handle conditions on both sides (when in weak vs. strict). So I
don't really understand where the gains of this would come from and it
actually causes me concern in that what if a developer forgets to define
strict and you're entire system is built on strict.In case this hasn't been repeated enough times already: No They Would Not.
As a library developer, you do not rely on strict or weak hints, you rely on
the variables you receive being of the types you require. This is guaranteed
in both modes.You cannot stop the user of your library doing whatever it takes to get past
your validation. It is up to them to provide sane inputs to your published
API, and no version of type hinting can change that.
This is mostly true, but relying on the variable that you receive
inside a function is different from relying on the variable that gets
passed to a function.
Yes, there will be users who will simply do an explicit cast, but
there will also be users who will take notice of the produced error,
and ask themselves why first, instead of immediately trying to
"override" it.
Many developers want to do that, regardless of the reasons why. Some
just like the strict philosophy better, some see it as a way of
educating their users, and others use it sparingly. Try arguing with
anybody writing crypto code and they will all tell you that any case
of uncertainty must be handled with a hard failure.
You may not agree that it is necessary, but that doesn't make it
invalid. And intentionally allowing only one guaranteed behavior does
imply that the other is invalid.
For the Nth time - if I want to achieve that effect, I will code for
both cases by not using the feature and doing is_int()
, is_string()
,
is_bool()
, etc. checks, so the language might as well help me do it. I
would understand if it was not helping with something that's just
wrong, but this is not the case at all here.
Cheers,
Andrey.
Andrey Andreev wrote on 16/01/2015 13:00:
Hi,
Mike Willbanks wrote on 15/01/2015 16:55:
It also means that then a library developer would
need to handle conditions on both sides (when in weak vs. strict). So I
don't really understand where the gains of this would come from and it
actually causes me concern in that what if a developer forgets to define
strict and you're entire system is built on strict.In case this hasn't been repeated enough times already: No They Would Not.
As a library developer, you do not rely on strict or weak hints, you rely on
the variables you receive being of the types you require. This is guaranteed
in both modes.You cannot stop the user of your library doing whatever it takes to get past
your validation. It is up to them to provide sane inputs to your published
API, and no version of type hinting can change that.
This is mostly true, but relying on the variable that you receive
inside a function is different from relying on the variable that gets
passed to a function.Yes, there will be users who will simply do an explicit cast, but
there will also be users who will take notice of the produced error,
and ask themselves why first, instead of immediately trying to
"override" it.Many developers want to do that, regardless of the reasons why. Some
just like the strict philosophy better, some see it as a way of
educating their users, and others use it sparingly. Try arguing with
anybody writing crypto code and they will all tell you that any case
of uncertainty must be handled with a hard failure.You may not agree that it is necessary, but that doesn't make it
invalid. And intentionally allowing only one guaranteed behavior does
imply that the other is invalid.For the Nth time - if I want to achieve that effect, I will code for
both cases by not using the feature and doingis_int()
,is_string()
,
is_bool()
, etc. checks, so the language might as well help me do it. I
would understand if it was not helping with something that's just
wrong, but this is not the case at all here.
OK, point taken. I do think that it's a bad idea for library authors to
do that, so don't think the language should make it easy, but I
understand that some people want to do it.
Specifically, I don't think a library author should be able to tell me
that, just because they're feeling picky, '42' and 42 are not equivalent
when calling their function. It does very little to protect me from
genuine mistakes (passing completely the wrong parameter), and makes my
life as user of the library harder.
But then, fundamentally, that's the argument against having strict
typing full stop, and it's painfully clear that there's a big divide of
opinion on that.
Regards,
Rowan Collins
[IMSoP]
Hi again,
Specifically, I don't think a library author should be able to tell me that,
just because they're feeling picky, '42' and 42 are not equivalent when
calling their function. It does very little to protect me from genuine
mistakes (passing completely the wrong parameter), and makes my life as user
of the library harder.
With no attempt to argue, I just thought of another example, inspired
by the ones given in the RFC - it is fairly common for functions
dealing with times to only accept a UNIX timestamp or otherwise just a
single kind of a time unit, such as only a count of minutes or days.
So where '7 years' is passed and and accepted when using a weak hint
(by truncating the trailing non-numeric characters), a strict hint on
the other hand may prevent the input of incorrect data (given that
it's not years that are expected, of course).
While typing that, I thought of another possible improvement that may
be made regardless of strict, weak or no scalar type hints are
implemented. I'm not sure if it's feasible due to the
parser/compiler/whatever possibly not having access to this info, so I
hope that somebody confirms that ...
Can it be made for the error messages to mention the parameter name
instead of only its number?
Take the following example:
function fubar(string $data, int $mode) {}
fubar('dummy', 'non-integer');
A 'fubar() expects parameter 2 ($mode) to be integer, string given'
would be substantially more useful in case of wrong input.
Cheers,
Andrey.
Andrey Andreev wrote on 16/01/2015 15:37:
With no attempt to argue, I just thought of another example, inspired
by the ones given in the RFC - it is fairly common for functions
dealing with times to only accept a UNIX timestamp or otherwise just a
single kind of a time unit, such as only a count of minutes or days.So where '7 years' is passed and and accepted when using a weak hint
(by truncating the trailing non-numeric characters), a strict hint on
the other hand may prevent the input of incorrect data (given that
it's not years that are expected, of course).
That's a nice example of the advantage, actually, thank you.
However, it makes me think of another approach to the whole situation,
which is to make more use of Value Objects (now that the implementation
of objects is no longer a huge performance hog). Obviously, for a
timestamp, there is the built-in DateTimeInterface, but even if there
weren't, it would be trivial to create something which existed only for
type-checking a kind of sub-classed integer:
class UnixTimestamp { private $value; public function get_value() {
return $this->value } public function __construct($new_value) { /*
validate input */ } }
Obviously, the validation would still need to be written, but it would
be tucked away in the shared class, rather than pasted as boilerplate at
the top of every function.
In many situations, the type of the argument isn't really "int" or
"string", it's "mode" (from an enum or bitmask), or "text label" (maybe
needs translation support) etc. So a library that really wants to
document its type system should be providing wrappers for all these
value types, at which point it can type hint them all by class or
interface anyway.
Scalar type hinting falls into the in-between category of "I want my
code to be type-safe, but using a very flat type system which makes only
loose guarantees about the data".
Regards,
Rowan Collins
[IMSoP]
I was just surprised by the current behavior :)
$ cat ops.php
<?php
function foo(string $str) {
}
foo("ops");
?>
$ sapi/cli/php -n ops.php
Catchable fatal error: Argument 1 passed to foo() must be an instance of
string, string given in ops.php on line 2
It too me time to realize what is going on :)
Thanks. Dmitry.
On Fri, Jan 16, 2015 at 6:58 PM, Rowan Collins rowan.collins@gmail.com
wrote:
Andrey Andreev wrote on 16/01/2015 15:37:
With no attempt to argue, I just thought of another example, inspired
by the ones given in the RFC - it is fairly common for functions
dealing with times to only accept a UNIX timestamp or otherwise just a
single kind of a time unit, such as only a count of minutes or days.So where '7 years' is passed and and accepted when using a weak hint
(by truncating the trailing non-numeric characters), a strict hint on
the other hand may prevent the input of incorrect data (given that
it's not years that are expected, of course).That's a nice example of the advantage, actually, thank you.
However, it makes me think of another approach to the whole situation,
which is to make more use of Value Objects (now that the implementation of
objects is no longer a huge performance hog). Obviously, for a timestamp,
there is the built-in DateTimeInterface, but even if there weren't, it
would be trivial to create something which existed only for type-checking a
kind of sub-classed integer:class UnixTimestamp { private $value; public function get_value() { return
$this->value } public function __construct($new_value) { /* validate input
*/ } }Obviously, the validation would still need to be written, but it would be
tucked away in the shared class, rather than pasted as boilerplate at the
top of every function.In many situations, the type of the argument isn't really "int" or
"string", it's "mode" (from an enum or bitmask), or "text label" (maybe
needs translation support) etc. So a library that really wants to document
its type system should be providing wrappers for all these value types, at
which point it can type hint them all by class or interface anyway.Scalar type hinting falls into the in-between category of "I want my code
to be type-safe, but using a very flat type system which makes only loose
guarantees about the data".Regards,
Rowan Collins
[IMSoP]
Hi!
We’re definitely not going to have consensus on introducing both options as
per this RFC. I for one think it’s the worst possible option.
I agree. Being wrong is bad, making a mistake is bad, but having split
personality language and not knowing in which world you are - or even
worse, having to deal with both worlds in the same code and being thrown
back and forth between them by some little switch which is easy to miss
- IMO is worse. I don't like strict typing in PHP because I think it is
contrary to the idea of how dynamic languages should work, but I'd
rather have that then two sets of rules living within the same code,
especially when looking at the function I can't even know how it would
work without checking if there's a declare hiding somewhere. And
refactoring becomes a nightmare - what if I moved function from strict
world to non-strict world or vice versa?
I also agree with Dmitry in other thread - if some conv rules are so bad
everybody hates them (or at least you think it is the case :), we can
change them. We are already on that track with some weird ones like
array->string. Even with BC effects, IMO better than too many sets of
rules.
Stas Malyshev
smalyshev@gmail.com
Hi Stas,
I agree. Being wrong is bad, making a mistake is bad, but having split
personality language and not knowing in which world you are - or even
worse, having to deal with both worlds in the same code and being thrown
back and forth between them by some little switch which is easy to miss
- IMO is worse. I don't like strict typing in PHP because I think it is
contrary to the idea of how dynamic languages should work, but I'd
rather have that then two sets of rules living within the same code,
especially when looking at the function I can't even know how it would
work without checking if there's a declare hiding somewhere. And
refactoring becomes a nightmare - what if I moved function from strict
world to non-strict world or vice versa?
It’s not about the location of the function, but the call site. You can place a function anywhere and it will behave identically.
I also agree with Dmitry in other thread - if some conv rules are so bad
everybody hates them (or at least you think it is the case :), we can
change them. We are already on that track with some weird ones like
array->string. Even with BC effects, IMO better than too many sets of
rules.
There are some minor issues with the conversion rules that could be fixed, but a lot of people have a problem not just with the conversion rules, but with the implicit conversion itself. The previous RFC (Scalar Type Hinting with Casts) wasn’t popular with many people for that reason: sure, it had stricter rules, but that won’t please people who want no conversion whatsoever.
Thanks.
Andrea Faulds
http://ajf.me/
Hi,
Hi Leigh,
I really don't like this behaviour being changed at the call site. If
I design a function that I know should only take a string, then I
want it to be an error if the user supplies anything else, so that
they know they messed up.I don’t like the idea of being forced to use strict (or weak) type checking because the API author decided as much.
What happens with that code:
$i = 1;
$a = myFunc( $i );
declare(strict_typehints=TRUE);
function myFunc( float $f )
{
return otherFunc( $f );
}
function otherFunc( float $f )
{
...
}
As author of strict code I need to replace
return otherFunc( $f );
by
return otherFunc( (float) $f );
I'm not sure
-
if this is what a strict coder wants and
-
if you find an acceptable way to test your strict code if it works
with non-strict code.
Regards
Thomas
Hi Thomas,
$i = 1;
$a = myFunc( $i );declare(strict_typehints=TRUE);
function myFunc( float $f )
{
return otherFunc( $f );
}function otherFunc( float $f )
{
...
}As author of strict code I need to replace
return otherFunc( $f );
by
return otherFunc( (float) $f );
I'm not sure
if this is what a strict coder wants and
if you find an acceptable way to test your strict code if it works with non-strict code.
I don’t understand, I’m sorry.
If you are using declare(strict_typehints=TRUE); then all calls in a file are “strict”. If you are not, all calls in a file are “weak”.
--
Andrea Faulds
http://ajf.me/
Hi Andrea,
Hi Thomas,
$i = 1;
$a = myFunc( $i );declare(strict_typehints=TRUE);
function myFunc( float $f )
{
return otherFunc( $f );
}function otherFunc( float $f )
{
...
}As author of strict code I need to replace
return otherFunc( $f );
by
return otherFunc( (float) $f );
I'm not sure
if this is what a strict coder wants and
if you find an acceptable way to test your strict code if it works with non-strict code.
I don’t understand, I’m sorry.
If you are using declare(strict_typehints=TRUE); then all calls in a file are “strict”. If you are not, all calls in a file are “weak”.
Sorry, if my mail was not clear. My point was: If I write a library in
strict mode and someone else is using it from his non-strict mode, he
can pass an integer to myFunc() without an error. If I use this integer
in my library and hand it over to otherFunc() (in my library) this will
fail as integer is not accepted for float.
Or did I misunderstood the RFC and there is a casting of the integer to
a float when calling myFunc()?
Regards
Thomas
Hi Thomas,
Sorry, if my mail was not clear. My point was: If I write a library in strict mode and someone else is using it from his non-strict mode, he can pass an integer to myFunc() without an error. If I use this integer in my library and hand it over to otherFunc() (in my library) this will fail as integer is not accepted for float.
Or did I misunderstood the RFC and there is a casting of the integer to a float when calling myFunc()?
The value would be casted, yes. From the function author’s perspective, there’s no need to worry about strict vs. weak typing: in both cases, you get the type you asked for.
Thanks.
--
Andrea Faulds
http://ajf.me/
Andrea Faulds wrote on 14/01/2015 13:15:
Hi Thomas,
Sorry, if my mail was not clear. My point was: If I write a library in strict mode and someone else is using it from his non-strict mode, he can pass an integer to myFunc() without an error. If I use this integer in my library and hand it over to otherFunc() (in my library) this will fail as integer is not accepted for float.
Or did I misunderstood the RFC and there is a casting of the integer to a float when calling myFunc()?
The value would be casted, yes. From the function author’s perspective, there’s no need to worry about strict vs. weak typing: in both cases, you get the type you asked for.
Perhaps it would be clearer if the RFC (and the documentation, if this
is accepted) referred to the non-strict as something other than "weak".
It makes it sound like only a weak check will be performed, and some
values of the "wrong" type will be allowed through, when in reality you
will always get exactly the type asked for.
Maybe "coercive type-checking" would more accurately reflect the
functionality?
Regards,
Rowan Collins
[IMSoP]
Hi Rowan,
Perhaps it would be clearer if the RFC (and the documentation, if this is accepted) referred to the non-strict as something other than "weak". It makes it sound like only a weak check will be performed, and some values of the "wrong" type will be allowed through, when in reality you will always get exactly the type asked for.
Maybe "coercive type-checking" would more accurately reflect the functionality?
Yeah, that’s an issue I’m aware of, “type checking" would suggest it merely “checks”, but it actually has the same implicit conversion behaviour used by extension and built-in PHP functions. I’m not sure what to call it. I don’t really think “coercive type-checking” is particularly better.
Anyone who has a suggestion for a name, please feel free to offer it.
Thanks.
Andrea Faulds
http://ajf.me/
Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and
bumped its version to 0.2.Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC,
so it’d be sensible to separate discussion of the updated RFC from the v0.1
RFC.Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/
Hello,
Using declare() IMO, is a PITA.
Everything that can be done without the use of declare(), must be done
without declare().
I would have prefered different syntax, like the ones we disccussed many
years ago , having strict checks with the foo(string $a) syntax, and
non-strict check with the foo((string) $a) syntax.
Julien.P
Hi Julien,
Using declare() IMO, is a PITA.
Everything that can be done without the use of declare(), must be done without declare().I would have prefered different syntax, like the ones we disccussed many years ago , having strict checks with the foo(string $a) syntax, and non-strict check with the foo((string) $a) syntax.
Actually, this approach came about mostly to avoid that. I don’t really like the idea of mixing and matching weak and strict type checks. Having some functions using (int) and (string), others use int and string, and others still use both, would be confusing. Plus, it would mean that you’d be forced to follow the personal preference of the API authors.
With this RFC, yes, you have to put an extra line at the top of the file. But it has the advantage that everything follows the same behaviour, even extension/built-in functions. That’s what I like about it.
--
Andrea Faulds
http://ajf.me/
Hello,
Hi Julien,
Using declare() IMO, is a PITA.
Everything that can be done without the use of declare(), must be done without declare().I would have prefered different syntax, like the ones we disccussed many years ago , having strict checks with the foo(string $a) syntax, and non-strict check with the foo((string) $a) syntax.
Actually, this approach came about mostly to avoid that. I don’t really like the idea of mixing and matching weak and strict type checks. Having some functions using (int) and (string), others use int and string, and others still use both, would be confusing. Plus, it would mean that you’d be forced to follow the personal preference of the API authors.
With this RFC, yes, you have to put an extra line at the top of the file. But it has the advantage that everything follows the same behaviour, even extension/built-in functions. That’s what I like about it.
I don't understand why it should be a bad thing that the API author
forces rules on the consumer. The opposite is IMO fundamental to the
concept of an API - the rules specified by the author are a contract
that the consumer agrees to, and which allows for the whole thing to
work properly.
In this form, I don't get any benefit from strict type checks, because
I only want them so that writing foo(int $bar) guarantees me that the
caller passed an integer. Instead, I'd have to NOT use a type hint,
and instead do an is_int($bar) check inside ... this beats the whole
purpose.
This caller-controlled switch very much reminds me of
mbstring.func_overload, which I didn't care much for, until one day I
saw how it breaks all crypto code that authors had otherwise written
very carefully.
I prefer Julien's (int) $weak vs. int $strong syntax better (which is
what I've always wanted), but I don't care much if it's a declare()
statement, just as long as the author controls the behavior.
And while I'm on that - thank you for this proposal (specifically the
0.2 version), Andrea. Finally an RFC that allows both weak and strict
scalar type checks instead of the "can't go in both directions"
nonsense that has blocked this feature for years.
Cheers,
Andrey.
Hi Andrey,
I don't understand why it should be a bad thing that the API author
forces rules on the consumer. The opposite is IMO fundamental to the
concept of an API - the rules specified by the author are a contract
that the consumer agrees to, and which allows for the whole thing to
work properly.In this form, I don't get any benefit from strict type checks, because
I only want them so that writing foo(int $bar) guarantees me that the
caller passed an integer. Instead, I'd have to NOT use a type hint,
and instead do an is_int($bar) check inside ... this beats the whole
purpose.
Why? What is wrong with a caller choosing to use weak type hints? Either way you receive an integer.
This caller-controlled switch very much reminds me of
mbstring.func_overload, which I didn't care much for, until one day I
saw how it breaks all crypto code that authors had otherwise written
very carefully.I prefer Julien's (int) $weak vs. int $strong syntax better (which is
what I've always wanted), but I don't care much if it's a declare()
statement, just as long as the author controls the behavior.
And while I'm on that - thank you for this proposal (specifically the
0.2 version), Andrea. Finally an RFC that allows both weak and strict
scalar type checks instead of the "can't go in both directions"
nonsense that has blocked this feature for years.
I don’t like going in both directions if I’ll have to deal with both at the same time. I want consistency. Either everything weak or everything strict. That’s why I like this approach. At least within a single file, everything will follow the same approach, rather than it being mix-and-match.
--
Andrea Faulds
http://ajf.me/
Hi again,
Hi Andrey,
I don't understand why it should be a bad thing that the API author
forces rules on the consumer. The opposite is IMO fundamental to the
concept of an API - the rules specified by the author are a contract
that the consumer agrees to, and which allows for the whole thing to
work properly.In this form, I don't get any benefit from strict type checks, because
I only want them so that writing foo(int $bar) guarantees me that the
caller passed an integer. Instead, I'd have to NOT use a type hint,
and instead do an is_int($bar) check inside ... this beats the whole
purpose.Why? What is wrong with a caller choosing to use weak type hints? Either way you receive an integer.
Because it's pointless. Why would I want strict checks if I only cared
for getting an integer? The whole point is that I care for what the
caller passed, that I want specifically a check instead of a cast.
Cheers,
Andrey.
Hi Andrea,
I have some notes about this RFC from a users POV with only little
knowledge about internals.
I didn't read 100% of the theads of this RFC so I'm sorry if some notes
of this email was already discussed.
- Inconsistencies of ZPP and explicit casts
In my opinion it should be the same if you call a function in weak type
mode and calling a function in strict type mode with explicit cast.
But that would require to remove inconsistencies of ZPP and explicit casts.
- Only one choice for the language
In my opinion scalar types should be hinted strict and the caller of an
API have to be sure to pass the right types. The caller have to know
about the function he calls and he already should know what the function
expects. This is the point were the caller have to know the type of an
expected argument and he should know his own types. So he is the one how
can pass the variable or make an explicit type cast.
To do so see [1]
- Reserved words
I don't like it adding so much reserved words.
As I understand it correctly the reservation is because of naming
collisions on type-hints with scalars and classes/interfaces.
Why not adding these types as classes (marked final and not allowed to
be initialized for know)?
Than you can use the already existing standards of classes as type-hints.
This would allow you using your own class of a different namespace with
the same name and would reduce BC break drastically.
The only consequence would be that you have to reference the root
namespace or import (use) the classes of the root namespace to use the
type-hints.
As sugar it should be possible to use inheritance and polymorphism to
better hint what you really need.
E.g.: class Integer extends Scalar implements Numeric
- Only one naming
I dislike the proposed aliases. The type names should be defined once
without aliases and the manual and error massages should be changed to
be consistent.
Because of PHP internally already allows different names this should
persist to be BC safe but should be reviewed and documented what is the
real type name and what are aliases. The aliases could be deprecated in
another RFC.
Btw. The type float is used also as double and real. I don't see if
these aliases are supported in your RFC or not.
Marc
Am 14.01.2015 um 01:16 schrieb Andrea Faulds:
Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/
Hi Marc,
- Inconsistencies of ZPP and explicit casts
In my opinion it should be the same if you call a function in weak type mode and calling a function in strict type mode with explicit cast.
But that would require to remove inconsistencies of ZPP and explicit casts.
Explicit casts and implicit casts have different behaviour, and that is definitely a good thing. Implicit casts can and should fail if the conversion isn’t sensible. Explicit casts aren’t supposed to fail.
- Only one choice for the language
In my opinion scalar types should be hinted strict and the caller of an API have to be sure to pass the right types. The caller have to know about the function he calls and he already should know what the function expects. This is the point were the caller have to know the type of an expected argument and he should know his own types. So he is the one how can pass the variable or make an explicit type cast.
This is all very well and good, and strict typing has its advantages, but there are a lot of people who do not want to have to deal with a strictly-typed API.
- Reserved words
I don't like it adding so much reserved words.
This doesn’t add any reserved words. It prevents the usage of some names for class names.
As I understand it correctly the reservation is because of naming collisions on type-hints with scalars and classes/interfaces.
Why not adding these types as classes (marked final and not allowed to be initialized for know)?
Because then you’d have to do this at the top of every single file:
use php\typehint\int;
use php\typehint\float;
use php\typehint\string;
use php\typehint\bool;
Considering how much people seem to dislike the idea of using declare() for strict typing, I can see how poorly that would go down.
More importantly, this would be inconsistent with our existing type hints like array and callable.
- Only one naming
I dislike the proposed aliases. The type names should be defined once without aliases and the manual and error massages should be changed to be consistent.
In an ideal world we would only have the short or long form, sure. But this isn’t an ideal world, and PHP doesn’t have compile-time validation of type hints. It would be too easy to write foo(integer $bar) and miss that it is broken if the function isn’t called.
I don’t think having both int and integer is really a problem. It’s not going to cause confusion, they are obviously the same type. Coding style guides will mandate one or the other.
Thanks.
Andrea Faulds
http://ajf.me/
Am 14.01.2015 um 23:39 schrieb Andrea Faulds:
Hi Marc,
- Inconsistencies of ZPP and explicit casts
In my opinion it should be the same if you call a function in weak type mode and calling a function in strict type mode with explicit cast.
But that would require to remove inconsistencies of ZPP and explicit casts.
Explicit casts and implicit casts have different behaviour, and that is definitely a good thing. Implicit casts can and should fail if the conversion isn’t sensible. Explicit casts aren’t supposed to fail.
That's a big problem for the strict type mode because of you have to
explicit cast to pass function signature which would result in a much
unsafer behavior were you originally wont a strict behavior. The only
way to be safe would be to use extra function calls for casting.
- Only one choice for the language
In my opinion scalar types should be hinted strict and the caller of an API have to be sure to pass the right types. The caller have to know about the function he calls and he already should know what the function expects. This is the point were the caller have to know the type of an expected argument and he should know his own types. So he is the one how can pass the variable or make an explicit type cast.
This is all very well and good, and strict typing has its advantages, but there are a lot of people who do not want to have to deal with a strictly-typed API.
It's only a personal feeling for scrict typing but it requires casting
to be fixed.
But I have to agree with that casting is part of the caller with or
without this choice.
The library author only defines the type he requires but the caller is
the one have have to do so. Week typing in this case only helps the
caller to automatically cast.
- Reserved words
I don't like it adding so much reserved words.
This doesn’t add any reserved words. It prevents the usage of some names for class names.
Preventing usage of some names means the same as reserved names at least
in the contest of class names.
As I understand it correctly the reservation is because of naming collisions on type-hints with scalars and classes/interfaces.
Why not adding these types as classes (marked final and not allowed to be initialized for now)?
Because then you’d have to do this at the top of every single file:use php\typehint\int;
use php\typehint\float;
use php\typehint\string;
use php\typehint\bool;Considering how much people seem to dislike the idea of using declare() for strict typing, I can see how poorly that would go down.
Such types should be on the root namespace. So the only difference would
be a backslash and only if you are within a namespace.
And to reaped myself you can do vary useful:
// internal pseudo code
class Scalar {}
interface Numeric {}
class Integer extends Scalar implements Numeric {}
class Float extends Scalar implements Numeric {}
class String extends Scalar {}
class Array implements Traversable {}
// users code
function increment(numeric $num) { return $num + 1; }
function incrementInt(integer $int) { return $int + 1; }
function incrementFloat(float $float) { return $float + 1; }
// in namespace
function increment(\numeric $num) { return $num + 1; }
function incrementInt(\integer $int) { return $int + 1; }
function incrementFloat(\float $float) { return $float + 1; }
More importantly, this would be inconsistent with our existing type hints like array and callable.
It would only be inconsistent if you don't think it through end but sure
it's more work. I have no idea how much.
On calling a function in week mode one or more magic methods could be
used to add auto cast behavior like:
public function __toInt();
public function __toFloat();
public function __toString(); // it will be called already
public function __toArray(); // Not part of this RFC
public function __toInstanceOf($name); // Will be called if no one of
the other pass
- Only one naming
I dislike the proposed aliases. The type names should be defined once without aliases and the manual and error massages should be changed to be consistent.
In an ideal world we would only have the short or long form, sure. But this isn’t an ideal world, and PHP doesn’t have compile-time validation of type hints. It would be too easy to write foo(integer $bar) and miss that it is broken if the function isn’t called.
Please let us make PHP more ideal ;)
Your argument is nonsense. As long as you never test your (unittest or
manual) you can't be sure to work well. The same argument could pass for
current type-hinting. If that argument is serious you have to eg.
automatically fix type errors in class names.
Btw. IDEs already warn if you use something undeclared project wide.
I don’t think having both int and integer is really a problem. It’s not going to cause confusion, they are obviously the same type. Coding style guides will mandate one or the other.
What about double and real?
Thanks.
Andrea Faulds
http://ajf.me/
Thanks
Marc
In my opinion, version 0.1 was consistent enough.
handling two different approaches just makes mess...
We have internal function strlen(string $s), and it may be called with
integer argument e.g. strlen(123) -> 3
I think user functions should follow the same rules.
If some rules are "bad", lets change that rules for both internal and user
functions.
But it's better to do it in a separate RFC (after scalar type hinting 0.1
accepted), or we will stick forever.
Thanks. Dmitry.
Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and
bumped its version to 0.2.Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC,
so it’d be sensible to separate discussion of the updated RFC from the v0.1
RFC.Please tell me your thoughts.
Thanks!
Andrea Faulds
http://ajf.me/
Hey Dmitry,
In my opinion, version 0.1 was consistent enough.
handling two different approaches just makes mess...
We have internal function strlen(string $s), and it may be called with integer argument e.g. strlen(123) -> 3
I think user functions should follow the same rules.
This RFC does that. In the “weak” mode that would continue work, and it would also for userland functions with scalar type hints. In the “strict” mode that would break, and it would also break for a similar userland function with a scalar type hint.
If some rules are "bad", lets change that rules for both internal and user functions.
But it's better to do it in a separate RFC (after scalar type hinting 0.1 accepted), or we will stick forever.
I’m not sure the weak typing approach to function parameters is bad per se, but a lot of developers would certainly prefer the strict typing approach. That’s why the RFC allows choice: for all the people that weak typing works for, good, you can keep using that. The people who want strict typing get strict typing without forcing the people who want weak typing to use it.
Thanks.
Andrea Faulds
http://ajf.me/
Hey:
Hey Dmitry,
In my opinion, version 0.1 was consistent enough.
handling two different approaches just makes mess...
We have internal function strlen(string $s), and it may be called with integer argument e.g. strlen(123) -> 3
I think user functions should follow the same rules.This RFC does that. In the “weak” mode that would continue work, and it would also for userland functions with scalar type hints. In the “strict” mode that would break, and it would also break for a similar userland function with a scalar type hint.
sounds like a hell to me.....
sorry for saying that, but I don't like the whole "declare" thing...
could we please strict to v0.1, only make it first ?
thanks
If some rules are "bad", lets change that rules for both internal and user functions.
But it's better to do it in a separate RFC (after scalar type hinting 0.1 accepted), or we will stick forever.I’m not sure the weak typing approach to function parameters is bad per se, but a lot of developers would certainly prefer the strict typing approach. That’s why the RFC allows choice: for all the people that weak typing works for, good, you can keep using that. The people who want strict typing get strict typing without forcing the people who want weak typing to use it.
Thanks.
Andrea Faulds
http://ajf.me/--
--
Xinchen Hui
@Laruence
http://www.laruence.com/
hi Andrea,
Good evening,
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
As much as I like the concept, it adds a bit too much confusions and
options for my taste.
My feeling (as you and other said already many many times), a
relatively large part of the users would prefer strict type hinting
over something that relies on the current conversion behaviors, for
clarity. There are still some people opposed to strict hinting or
opposed to hinting but that was pretty much the same when we discussed
the additions of OO related features.
Instead of having one option full of compromises, I would suggest to
go with the 0.1 version with two options, strict and matching the
current conversions behaviors and move on. No matter how we look at
it, there is no way we can find compromises between one or the other
solution. It is only about strict or current conversions, everything
else is going to be an endless discussion about the exact same
arguments, pros, cons, etc.
Cheers,
Pierre
@pierrejoye | http://www.libgd.org
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Reading the thread at this point shows so much confusion, it seems half
the people reading the spec misunderstood that the declare() line
affects function calls only and not the API/implementation level.
As much I think it was a smart idea and workaround, it is perhaps too
clever for its own good if nobody gets it.
Anyway, as v0.2 appears to be v0.1 + declare(), why not keep those two
options separated in the vote?
a) should be add weak typing
b) should we also add declare() for to get strict typing at call-site.
If a passes it would be a great stepping stone towards adding b
later perhaps, or tweaking internal coercion rules to improve the
behavior of the weak types, having scalars in return hints (since return
hints seem likely to pass), etc.
If b passes as well great we have a complete picture and every team
can have declare() Y/N in their own coding guidelines based on preference.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
Reading the thread at this point shows so much confusion, it seems half the
people reading the spec misunderstood that the declare() line affects
function calls only and not the API/implementation level.As much I think it was a smart idea and workaround, it is perhaps too clever
for its own good if nobody gets it.Anyway, as v0.2 appears to be v0.1 + declare(), why not keep those two
options separated in the vote?a) should be add weak typing
b) should we also add declare() for to get strict typing at call-site.If a passes it would be a great stepping stone towards adding b later
perhaps, or tweaking internal coercion rules to improve the behavior of the
weak types, having scalars in return hints (since return hints seem likely
to pass), etc.If b passes as well great we have a complete picture and every team can
have declare() Y/N in their own coding guidelines based on preference.
Yeah, while the confusion is definitely still there, I would
personally argue that definitely some people who oppose the declare()
get that it's only for calls in the file - and still don't find it
clever.
The potential issues with this are pretty real, to be honest. Simple
things like moving a method from one class to another (let's say to
parent or descendant) and getting to another typing context may cause
unpredictable behavior if the user forgets to have declare() in both
files.
Pavel Kouril
On Thu, Jan 15, 2015 at 4:11 PM, Jordi Boggiano j.boggiano@seld.be
wrote:Reading the thread at this point shows so much confusion, it seems half
the
people reading the spec misunderstood that the declare() line affects
function calls only and not the API/implementation level.As much I think it was a smart idea and workaround, it is perhaps too
clever
for its own good if nobody gets it.Anyway, as v0.2 appears to be v0.1 + declare(), why not keep those two
options separated in the vote?a) should be add weak typing
b) should we also add declare() for to get strict typing at call-site.If a passes it would be a great stepping stone towards adding b later
perhaps, or tweaking internal coercion rules to improve the behavior of
the
weak types, having scalars in return hints (since return hints seem
likely
to pass), etc.If b passes as well great we have a complete picture and every team can
have declare() Y/N in their own coding guidelines based on preference.Yeah, while the confusion is definitely still there, I would
personally argue that definitely some people who oppose the declare()
get that it's only for calls in the file - and still don't find it
clever.The potential issues with this are pretty real, to be honest. Simple
things like moving a method from one class to another (let's say to
parent or descendant) and getting to another typing context may cause
unpredictable behavior if the user forgets to have declare() in both
files.
This alone is a very big argument against it imho. Next argument
would be using different libraries in one file and wanting one of them
to be strict the other not.
I get the idea following something like "use strict;" approaches of
Perl/Javascript,
however AFAIK they only affect the file itself, not calls from the file to
another one.
Pavel Kouril
The potential issues with this are pretty real, to be honest. Simple things like moving a method from one class to another (let's say to parent or descendant) and getting to another typing context may cause unpredictable behavior if the user forgets to have declare() in both files.
This alone is a very big argument against it imho. Next argument
would be using different libraries in one file and wanting one of them
to be strict the other not.
If you want both you can just use the non-strict default and do type
checks yourself where you see fit.
If you had strict typing only or weak only you anyway could not choose
which library should be strict, each library would decide for you.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
The potential issues with this are pretty real, to be honest. Simple
things like moving a method from one class to another (let's say to
parent or descendant) and getting to another typing context may cause
unpredictable behavior if the user forgets to have declare() in both
files.
Agreed there are gotchas but not only with declare().
Many things can go wrong when you move a function somewhere else, for
example you might leave use
statements behind and suddenly a catch (FooException $e)
will fail to match exceptions or something sneaky
like that. I don't necessarily think that's enough to kill the feature.
Note that you can only get problems going from weak to strict context by
the way, the other way around should not cause any issues, code would
just work when it otherwise would have triggered strict errors. Since
you usually move code into places you own, I'd assume you know it if you
are using strict typing.
Cheers
--
Jordi Boggiano
@seldaek - http://nelm.io/jordi
Hi Pavel,
Reading the thread at this point shows so much confusion, it seems half the
people reading the spec misunderstood that the declare() line affects
function calls only and not the API/implementation level.Yeah, while the confusion is definitely still there, I would
personally argue that definitely some people who oppose the declare()
get that it's only for calls in the file - and still don't find it
clever.The potential issues with this are pretty real, to be honest. Simple
things like moving a method from one class to another (let's say to
parent or descendant) and getting to another typing context may cause
unpredictable behavior if the user forgets to have declare() in both
files.
This is true, you would sometimes have problems if you’re mixing the strict and weak type checking modes in your codebase.
The intention is that you’d use one or the other exclusively, perhaps with some minor exceptions as and where necessary. The fact it’s weak by default means you could add scalar type hints gradually without breaking things, because the weak mode is quite permissive. Then, if you wanted to, you could gradually migrate each file in your codebase over to strict mode.
Essentially, you get “gradual typing” like Hack, but without Hack’s approach which I don’t particularly like. Hack’s approach is to simply not enforce type hints if they’re a problem. On the other hand, this RFC would alway enforces them, but the weak mode is less strict.
So, I anticipate that while it would cause problems during a transition, I think codebases would end up using one mode or the other exclusively and wouldn’t have problems once they had done so.
Thanks.
Andrea Faulds
http://ajf.me/
Hi Jordi,
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Reading the thread at this point shows so much confusion, it seems half the people reading the spec misunderstood that the declare() line affects function calls only and not the API/implementation level.
As much I think it was a smart idea and workaround, it is perhaps too clever for its own good if nobody gets it.
Anyway, as v0.2 appears to be v0.1 + declare(), why not keep those two options separated in the vote?
a) should be add weak typing
b) should we also add declare() for to get strict typing at call-site.If a passes it would be a great stepping stone towards adding b later perhaps, or tweaking internal coercion rules to improve the behavior of the weak types, having scalars in return hints (since return hints seem likely to pass), etc.
If b passes as well great we have a complete picture and every team can have declare() Y/N in their own coding guidelines based on preference.
I may consider another RFC that just does weak typing, or reviving v0.1 if this RFC doesn’t pass. But I’m not really sure about it. I’m not sure it’s fair on all the people who would prefer a strict approach.
Andrea Faulds
http://ajf.me/
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so
it’d be sensible to separate discussion of the updated RFC from the v0.1
RFC.Reading the thread at this point shows so much confusion, it seems half the
people reading the spec misunderstood that the declare() line affects function
calls only and not the API/implementation level.As much I think it was a smart idea and workaround, it is perhaps too clever
for its own good if nobody gets it.Anyway, as v0.2 appears to be v0.1 + declare(), why not keep those two options
separated in the vote?a) should be add weak typing
b) should we also add declare() for to get strict typing at call-site.
What about a :
c) should we also add declare() for to get strict typing at
declaration-site.
It could be the author of a library deciding whether they prefer strict
type "hints". But then again, it doesn't really matter as long as the
library's method get the correct type I suppose.
cheers,
Derick
Hello together,
I have followed the discussion from the outside (as I am not to vote
here) but I am a (not representative) PHP developer.
I think the main problem here is that you mix two things up:
- Scalar type hints for functions
- Conversion rules
From what I have read, most of you agree that scalar type hints for
functions are really useful. If you define function foo(int $i) you
don't want is_int-checks and throw InvalidArgumentExceptions.
The real controversy is about what variables can be passed to the type
hinted functions. And that falls into 2)
There seem to be two types of conversion currently present in the code:
-
the one used for arguments of build-in/extension functions
max("1", 2.0); -
the one used for implicit conversion in php code
$i = "1" + 2.0;
The discussion now revolves around: which of both conversions is right
if I typehint my pure PHP function? Or are both wrong? I feel there
should be a separate RFC that addresses a unification of implicit
conversion rules and that matter should not be in the type hinting
discussion.
Thanks for listening,
Dennis Birkholz
I’ve made some quite significant changes to my Scalar Type Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
I don't like this at all. I'd prefer raising a new warning type (e.g.,
E_AUTOCAST) over this.
Does the voting system support instant-runoffs? If people could rate
their preferences of:
- strict scalar types
- weak scalar types (auto cast)
- both - different syntaxes. e.g, (int) $foo vs int $foo
- no scalar types
we could reach a compromised consensus without some building
Frankenstein. I really think having either basic strict or weak types
is far preferred to nothing. There are good arguments on both sides
... let the voters decide.
After that, additional RFCs could be created to address raising errors
on auto case, using declares to toggle behavior, etc - depending of
course on what was decided on prior vote.
--
Matthew Leverton
Hi Matthew,
I don't like this at all. I'd prefer raising a new warning type (e.g.,
E_AUTOCAST) over this.
That error type would cause absolute chaos, unless people decided not to make use of it. Custom error handlers are global and affect all code, including in libraries.
I can’t see how this would be even slightly useful.
Does the voting system support instant-runoffs? If people could rate
their preferences of:
- strict scalar types
- weak scalar types (auto cast)
- both - different syntaxes. e.g, (int) $foo vs int $foo
- no scalar types
we could reach a compromised consensus without some building
Frankenstein.
I don’t think supporting both approaches is really a “Frankenstein”. It would work out quite cleanly in practice.
I had considered holding multiple votes, but I decided against it.
Thanks.
Andrea Faulds
http://ajf.me/
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
Thanks!
Andrea Faulds
http://ajf.me/
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.
declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.
From the RFC text, I didn't completely understand, if declare() affects
call site or declaration. Will we able to call the same function using weak
type hinting from on file and with strict from the other?
"The strict type checking mode also affects extension and built-in PHP
functions", sin(1) - error !!!
Strict type hinting is not suitable for PHP by definition (as a weakly
typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about introducing
ability to switch to "strict" type hinting in context of use-cases.
Thanks. Dmitry.
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types
RFC has passed. The patch is a work in progress: it works, but lacks tests
for return types.Version 0.3 of the RFC can be found here:
https://wiki.php.net/rfc/scalar_type_hintsThanks!
Andrea Faulds
http://ajf.me/
Hi Dmitry,
--
Andrea Faulds
http://ajf.me/
As I already told, in my opinion, version 0.1 was the perfect solution that fit into PHP semantic very well.
declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict type hinting in a big project, people will have to change every single PHP file.
From the RFC text, I didn't completely understand, if declare() affects call site or declaration. Will we able to call the same function using weak type hinting from on file and with strict from the other?
"The strict type checking mode also affects extension and built-in PHP functions", sin(1) - error !!!Strict type hinting is not suitable for PHP by definition (as a weakly typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about introducing ability to switch to "strict" type hinting in context of use-cases.Thanks. Dmitry.
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
Thanks!
Andrea Faulds
http://ajf.me/
Hi Dmitry,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.
I don't like the original. Weak types work to a degree, but they don't fulfill the use case of a lot of developers, and consequently the RFC wasn't too popular outside internals.
declare(strict_types=1); - is really weird solution.
It is unusual, that is true. But it has some benefits.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.
From the RFC text, I didn't completely understand, if declare() affects
call site or declaration.
Ah, my bad. It affects function calls and return statements within the declare block, or remainder of the file if there's no declare block. So parameter types are checked using the mode chosen by the calling code, while return types are checked using the mode chosen by the called code.
Will we able to call the same function using weak
type hinting from on file and with strict from the other?
Yes, for the parameter type hints anyway. That means that strict and weak code is interoperable without enforcing a model on each other.
"The strict type checking mode also affects extension and built-in PHP
functions", sin(1) - error !!!
That particular case is probably unpopular - although strict type hinting for ints and floats can prevent nastier errors later (float out of int range, or silent loss of precision from int to float).
Strict type hinting is not suitable for PHP by definition (as a weakly
typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about introducing
ability to switch to "strict" type hinting in context of use-cases.
That'd be possible, but I fear that we'd just end up with weak typing only and no strict solution. Regardless of its merits, a large portion of the community is in favour of a strictly-typed solution. There are also a lot of people who are in favour of weak typing. So, this RFC tries to make a compromise.
Thanks.
--
Andrea Faulds
http://ajf.me/
Hi,
Hi Dmitry,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.I don't like the original. Weak types work to a degree, but they don't fulfill the use case of a lot of developers, and consequently the RFC wasn't too popular outside internals.
I still think that caller-controlled "strict mode" doesn't fulfill
that use case either.
Cheers,
Andrey.
Hi Andrey,
Hi,
Hi Dmitry,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.I don't like the original. Weak types work to a degree, but they don't fulfill the use case of a lot of developers, and consequently the RFC wasn't too popular outside internals.
I still think that caller-controlled "strict mode" doesn't fulfill
that use case either.
How doesn't it? It doesn't force the model upon your users, sure, but something like that is never going to get past internals anyway.
--
Andrea Faulds
http://ajf.me/
Hi Andrea,
Hi Andrey,
Hi,
Hi Dmitry,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.I don't like the original. Weak types work to a degree, but they don't fulfill the use case of a lot of developers, and consequently the RFC wasn't too popular outside internals.
I still think that caller-controlled "strict mode" doesn't fulfill
that use case either.How doesn't it? It doesn't force the model upon your users, sure, but something like that is never going to get past internals anyway.
We already had a long exchange of arguments on this, there's no point
in repeating them. But if you're concerned about it getting approved
by internals ... is there anybody on internals supporting this version
of it? I might've missed a mail or two, but so far I've seen only
criticism.
Cheers,
Andrey.
Hi Dmitry,
As I already told, in my opinion, version 0.1 was the perfect solution
that
fit into PHP semantic very well.I don't like the original. Weak types work to a degree, but they don't
fulfill the use case of a lot of developers, and consequently the RFC
wasn't too popular outside internals.
I sent a separate email to collect use-cases for strict typing. Please,
answer there.
declare(strict_types=1); - is really weird solution.
It is unusual, that is true. But it has some benefits.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single
PHP
file.
From the RFC text, I didn't completely understand, if declare() affects
call site or declaration.ansAh, my bad. It affects function calls and return statements within the
declare block, or remainder of the file if there's no declare block. So
parameter types are checked using the mode chosen by the calling code,
while return types are checked using the mode chosen by the called code.
not your bad, it's exactly what I read, I just couldn't believe that.
Will we able to call the same function using weak
type hinting from on file and with strict from the other?Yes, for the parameter type hints anyway. That means that strict and weak
code is interoperable without enforcing a model on each other.
At first I thought, this is ugly solution. Now I'm not completely sure.
"The strict type checking mode also affects extension and built-in PHP
functions", sin(1) - error !!!That particular case is probably unpopular - although strict type hinting
for ints and floats can prevent nastier errors later (float out of int
range, or silent loss of precision from int to float).
I see, but this would require declare(strict_types=1) everywhere that would
turn PHP into Java.
Strict type hinting is not suitable for PHP by definition (as a weakly
typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about
introducing
ability to switch to "strict" type hinting in context of use-cases.That'd be possible, but I fear that we'd just end up with weak typing only
and no strict solution. Regardless of its merits, a large portion of the
community is in favour of a strictly-typed solution. There are also a lot
of people who are in favour of weak typing. So, this RFC tries to make a
compromise.
I see, but I afraid that compromise is worse than one or the other.
Thanks. Dmitry.
Thanks.
--
Andrea Faulds
http://ajf.me/
Hi Dmitry,
Will we able to call the same function using weak
type hinting from on file and with strict from the other?Yes, for the parameter type hints anyway. That means that strict and weak code is interoperable without enforcing a model on each other.
At first I thought, this is ugly solution. Now I'm not completely sure.
I did as well when I first saw the idea proposed (someone else originally suggested it). It does seem ugly on the surface, but it has some advantages. Sure, you have to add this extra line of code to each file, that’s annoying. But, it means full backwards-compatibility, easier migration of existing codebases, and most importantly, allows people to choose one mode or another without affecting other users that have to call their code.
I see, but this would require declare(strict_types=1) everywhere that would turn PHP into Java.
Well, not quite Java, but yes. Typing it out is annoying. But it’s better than implicit strict typing for a directory, and it means we avoid having two or three different kinds of scalar type hint, so there’s no mixing of systems within the same file.
After a while I think people will get used to it. PHP programmers already have to type out "<?php namespace foobar;” at the start of each file, Perl programmers need "#!/usr/bin/perl” and “use warnings; use strict”, JS programmers need “(function () { ‘use strict’; }());” etc. Also, IDEs would help.
Strict type hinting is not suitable for PHP by definition (as a weakly
typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about introducing
ability to switch to "strict" type hinting in context of use-cases.That'd be possible, but I fear that we'd just end up with weak typing only and no strict solution. Regardless of its merits, a large portion of the community is in favour of a strictly-typed solution. There are also a lot of people who are in favour of weak typing. So, this RFC tries to make a compromise.
I see, but I afraid that compromise is worse than one or the other.
I’m actually convinced that this compromise is in some ways better than one or the other.
One of the nice things about strict mode only applying to code which asks for it, is that if a function if an API has type hints added, it won’t suddenly break calling code that didn’t strictly match types, if that calling code uses the default weak mode behaviour (which it will if it was written pre-PHP 7).
For example, say I have some sort of Response object that lets you set a body:
class Response {
public function setBody($message);
}
In PHP 5, it’s perfectly fine to pass something that’s not a string for $message:
$foo = new Response;
$foo->setBody(67);
Absurd example, but this sort of thing does happen in real world code, often accidentally.
Now, let’s say we add a string type hint in a new version of the library:
interface Response {
public function setBody(string $message);
}
If PHP’s type hints were always strict, then our existing PHP 5 code from earlier that took advantage of PHP’s weak typing would now produce an error:
Catchable fatal error: Argument 1 passed to Response::setBody() must be of the type string, integer given
This isn’t good - it makes migration of the existing codebase difficult.
Weak typing solves this problem because it allows conversions. However, it’s not really good that the code was passing an integer in the first place - it should really be passing a string.
The solution, then, is what this RFC offers. By default, weak typing is used, so your existing code doesn’t break initially. But once you’ve added type hints in a few places, you can switch to strict typing, and that error will be detected and can be fixed.
This way, we can have stricter types without sacrificing compatibility or complicating migration.
Thanks.
Andrea Faulds
http://ajf.me/
So, one of the advantages of strict type hinting is the ability to catch
potential errors.
For example when we pass 67 to setBody(string $message).
Thanks. Dmitry.
Hi Dmitry,
Will we able to call the same function using weak
type hinting from on file and with strict from the other?Yes, for the parameter type hints anyway. That means that strict and
weak code is interoperable without enforcing a model on each other.At first I thought, this is ugly solution. Now I'm not completely sure.
I did as well when I first saw the idea proposed (someone else originally
suggested it). It does seem ugly on the surface, but it has some
advantages. Sure, you have to add this extra line of code to each file,
that’s annoying. But, it means full backwards-compatibility, easier
migration of existing codebases, and most importantly, allows people to
choose one mode or another without affecting other users that have to call
their code.I see, but this would require declare(strict_types=1) everywhere that
would turn PHP into Java.Well, not quite Java, but yes. Typing it out is annoying. But it’s better
than implicit strict typing for a directory, and it means we avoid having
two or three different kinds of scalar type hint, so there’s no mixing of
systems within the same file.After a while I think people will get used to it. PHP programmers already
have to type out "<?php namespace foobar;” at the start of each file, Perl
programmers need "#!/usr/bin/perl” and “use warnings; use strict”, JS
programmers need “(function () { ‘use strict’; }());” etc. Also, IDEs would
help.Strict type hinting is not suitable for PHP by definition (as a weakly
typed language), however, I see, it may be useful in some cases.
I would prefer to have "weak" types at first, then think about
introducing
ability to switch to "strict" type hinting in context of use-cases.That'd be possible, but I fear that we'd just end up with weak typing
only and no strict solution. Regardless of its merits, a large portion of
the community is in favour of a strictly-typed solution. There are also a
lot of people who are in favour of weak typing. So, this RFC tries to make
a compromise.I see, but I afraid that compromise is worse than one or the other.
I’m actually convinced that this compromise is in some ways better than
one or the other.One of the nice things about strict mode only applying to code which asks
for it, is that if a function if an API has type hints added, it won’t
suddenly break calling code that didn’t strictly match types, if that
calling code uses the default weak mode behaviour (which it will if it was
written pre-PHP 7).For example, say I have some sort of Response object that lets you set a
body:class Response { public function setBody($message); }
In PHP 5, it’s perfectly fine to pass something that’s not a string for
$message:$foo = new Response; $foo->setBody(67);
Absurd example, but this sort of thing does happen in real world code,
often accidentally.Now, let’s say we add a string type hint in a new version of the library:
interface Response { public function setBody(string $message); }
If PHP’s type hints were always strict, then our existing PHP 5 code from
earlier that took advantage of PHP’s weak typing would now produce an error:Catchable fatal error: Argument 1 passed to Response::setBody() must
be of the type string, integer given
This isn’t good - it makes migration of the existing codebase difficult.
Weak typing solves this problem because it allows conversions. However,
it’s not really good that the code was passing an integer in the first
place - it should really be passing a string.The solution, then, is what this RFC offers. By default, weak typing is
used, so your existing code doesn’t break initially. But once you’ve added
type hints in a few places, you can switch to strict typing, and that error
will be detected and can be fixed.This way, we can have stricter types without sacrificing compatibility or
complicating migration.Thanks.
Andrea Faulds
http://ajf.me/
Hi Dmitry,
So, one of the advantages of strict type hinting is the ability to catch potential errors.
For example when we pass 67 to setBody(string $message).
Yes, that sort of thing is easily caught by strict type checks. They’re also able to catch things that are sometimes okay for weak hints, sometimes not. For example, some but not all strings are accepted for integer and float parameters, and some but not all floats are accepted for integer parameters. Strict checks make this much simpler and not dependant on the value: either some type is accepted, or it isn’t.
Because of that, strict types can actually be effectively analysed ahead-of-time by static analysers, IDEs and so on, and so you can catch some types of errors while editing your code, without even needing to run it. This is quite a powerful feature. Nikita might have more to say on that.
Thanks.
Andrea Faulds
http://ajf.me/
2015-02-02 21:12 GMT+02:00 Andrea Faulds ajf@ajf.me:
Hi Dmitry,
So, one of the advantages of strict type hinting is the ability to catch potential errors.
For example when we pass 67 to setBody(string $message).Yes, that sort of thing is easily caught by strict type checks. They’re also able to catch things that are sometimes okay for weak hints, sometimes not. For example, some but not all strings are accepted for integer and float parameters, and some but not all floats are accepted for integer parameters. Strict checks make this much simpler and not dependant on the value: either some type is accepted, or it isn’t.
Because of that, strict types can actually be effectively analysed ahead-of-time by static analysers, IDEs and so on, and so you can catch some types of errors while editing your code, without even needing to run it. This is quite a powerful feature. Nikita might have more to say on that.
Thanks.
Andrea Faulds
http://ajf.me/--
Strict type checking, has its advantages.
We all external data convert to native PHP types.
The database we use option MYSQLI_OPT_INT_AND_FLOAT_NATIVE.
Inputs are validated and converted to native PHP types.
In Redis data are stored as serialize string.
In our API we may require strict adherence to type because the integer
as strings $id = "123" to impossible, i need catch these as logical
error.
But I also fully endorse, cast without loss of accuracy, because it
gives you more options and less of a problem for those who do not have
the conversion of external data.
Not to discuss endlessly two options, it is reasonable send to voting
the Strict type checking, voting will be fail :), then will be easier
to discuss technical issues as do korektno cast without losing data,
good luck!
Hi Dmitry,
So, one of the advantages of strict type hinting is the ability to catch
potential errors.
For example when we pass 67 to setBody(string $message).Yes, that sort of thing is easily caught by strict type checks. They’re
also able to catch things that are sometimes okay for weak hints, sometimes
not. For example, some but not all strings are accepted for integer and
float parameters, and some but not all floats are accepted for integer
parameters. Strict checks make this much simpler and not dependant on the
value: either some type is accepted, or it isn’t.
Agree. Strict type checks are simple and may be implemented more efficient.
But in case we have to support both - weak and strict, this won't make any
advantage.
Because of that, strict types can actually be effectively analysed
ahead-of-time by static analysers, IDEs and so on, and so you can catch
some types of errors while editing your code, without even needing to run
it. This is quite a powerful feature. Nikita might have more to say on that.
Static analyzers can work with weak conversion rules as well.
Anyway, this is not directly related to run-time semantic we discuss now.
Thanks. Dmitry.
Thanks.
Andrea Faulds
http://ajf.me/
Hi Dmitry,
Agree. Strict type checks are simple and may be implemented more efficient.
But in case we have to support both - weak and strict, this won't make any advantage.
I think this still works even if we support both. The RFC’s approach means that within one file everything is strictly-typed, for example (except in rare cases of declare() block usage).
Static analyzers can work with weak conversion rules as well.
This is true, but weak conversion rules are less useful for error-checking in practice: for some conversions, you can’t say AOT if they’ll work or fail, just that they’ll “maybe” succeed. So I think analysis of strictly-typed code would be more effective.
Anyway, this is not directly related to run-time semantic we discuss now.
This is true.
Thanks.
Andrea Faulds
http://ajf.me/
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.
THis is why I believe it makes more sense to have this switch on the
callee side, instead of on the calling side.
cheers,
Derick
Hey Derick,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.THis is why I believe it makes more sense to have this switch on the
callee side, instead of on the calling side.
That does have its advantages. But it also has some quite severe problems.
For starters, if you set that flag on the callee side, you just broke everything that uses that function and passes the “wrong” type. That’s a migration headache.
It also means that you don’t have any choice over strictness as the user of an API: some APIs are strict, others weak. That means three lines of code might use three different approaches argument strictness. I don’t like that terribly much.
Thanks.
Andrea Faulds
http://ajf.me/
Hi,
Hey Derick,
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.THis is why I believe it makes more sense to have this switch on the
callee side, instead of on the calling side.That does have its advantages. But it also has some quite severe problems.
For starters, if you set that flag on the callee side, you just broke everything that uses that function and passes the “wrong” type. That’s a migration headache.
It also means that you don’t have any choice over strictness as the user of an API: some APIs are strict, others weak. That means three lines of code might use three different approaches argument strictness. I don’t like that terribly much.
As already said, we're just going around in circles at this point, but
a migration issue?
Whatever code using the scalar type hints should be new code in
userland. You're basing your whole argument on the assumption that all
internal functions would break with strict=1 ... nobody needs that and
it doesn't have to be done.
Cheers,
Andrey.
Hi Andrey,
As already said, we're just going around in circles at this point, but
a migration issue?Whatever code using the scalar type hints should be new code in
userland.
Why not existing userland code? If only new code adds type hints, the ability to detect errors in code is severely curtailed. That would be really unfortunate.
You're basing your whole argument on the assumption that all
internal functions would break with strict=1 ... nobody needs that and
it doesn't have to be done.
I wasn’t talking about internal functions… I’m talking about userland code in the hypothetical case that we added strict-only hints.
I don’t see where you’ve gotten that impression from.
Thanks.
Andrea Faulds
http://ajf.me/
Hi,
Hi Andrey,
As already said, we're just going around in circles at this point, but
a migration issue?Whatever code using the scalar type hints should be new code in
userland.Why not existing userland code? If only new code adds type hints, the ability to detect errors in code is severely curtailed. That would be really unfortunate.
You're basing your whole argument on the assumption that all
internal functions would break with strict=1 ... nobody needs that and
it doesn't have to be done.I wasn’t talking about internal functions… I’m talking about userland code in the hypothetical case that we added strict-only hints.
I don’t see where you’ve gotten that impression from.
Well ... existing userland code doesn't have scalar type hints, it
couldn't possibly do. How can you have migration issues with it?
Cheers,
Andrey.
Hi Andrey,
Hi Andrey,
As already said, we're just going around in circles at this point, but
a migration issue?Whatever code using the scalar type hints should be new code in
userland.Why not existing userland code? If only new code adds type hints, the ability to detect errors in code is severely curtailed. That would be really unfortunate.
You're basing your whole argument on the assumption that all
internal functions would break with strict=1 ... nobody needs that and
it doesn't have to be done.I wasn’t talking about internal functions… I’m talking about userland code in the hypothetical case that we added strict-only hints.
I don’t see where you’ve gotten that impression from.
Well ... existing userland code doesn't have scalar type hints, it
couldn't possibly do. How can you have migration issues with it?
I’ll just quote my previous message:
One of the nice things about strict mode only applying to code which asks for it, is that if a function if an API has type hints added, it won’t suddenly break calling code that didn’t strictly match types, if that calling code uses the default weak mode behaviour (which it will if it was written pre-PHP 7).
For example, say I have some sort of Response object that lets you set a body:
class Response {
public function setBody($message);
}In PHP 5, it’s perfectly fine to pass something that’s not a string for $message:
$foo = new Response;
$foo->setBody(67);Absurd example, but this sort of thing does happen in real world code, often accidentally.
Now, let’s say we add a string type hint in a new version of the library:
interface Response {
public function setBody(string $message);
}If PHP’s type hints were always strict, then our existing PHP 5 code from earlier that took advantage of PHP’s weak typing would now produce an error:
Catchable fatal error: Argument 1 passed to Response::setBody() must be of the type string, integer given
This isn’t good - it makes migration of the existing codebase difficult.
Weak typing solves this problem because it allows conversions. However, it’s not really good that the code was passing an integer in the first place - it should really be passing a string.
The solution, then, is what this RFC offers. By default, weak typing is used, so your existing code doesn’t break initially. But once you’ve added type hints in a few places, you can switch to strict typing, and that error will be detected and can be fixed.
This way, we can have stricter types without sacrificing compatibility or complicating migration.
Basically, strict-only types complicates their addition to existing codebases, including libraries.
What this RFC proposes is similar to Hack’s gradual typing, in a sense, in that it allows you to gradually add types to your codebase without breaking things.
--
Andrea Faulds
http://ajf.me/
Hi Andrey,
...
Just to give thanks to Andrea on persisting with a highly contentious RFC, one
that has defeated several others over the years. I hope that we will end up with
something acceptable to most and will be able to finally put this issue to bed.
Thanks again.
--
Alain Williams
Linux/GNU Consultant - Mail systems, Web sites, Networking, Programmer, IT Lecturer.
+44 (0) 787 668 0256 http://www.phcomp.co.uk/
Parliament Hill Computers Ltd. Registration Information: http://www.phcomp.co.uk/contact.php
#include <std_disclaimer.h
Hi Andrey,
...Just to give thanks to Andrea on persisting with a highly contentious
RFC, one
that has defeated several others over the years. I hope that we will
end up with
something acceptable to most and will be able to finally put this issue
to bed.
+1
I was describing this discussion to someone and said something about the compromise not giving everyone what they want, and he said "isn't that basically the definition of a compromise?"
This particular compromise is very well thought through on the whole, and I hope it at least leads the way out of the impasse of contrasting ideas by exploring ways to combine them.
Thanks Andrea!
Rowan Collins
[IMSoP]
Hi Andrey,
Hi Andrey,
As already said, we're just going around in circles at this point, but
a migration issue?Whatever code using the scalar type hints should be new code in
userland.Why not existing userland code? If only new code adds type hints, the ability to detect errors in code is severely curtailed. That would be really unfortunate.
You're basing your whole argument on the assumption that all
internal functions would break with strict=1 ... nobody needs that and
it doesn't have to be done.I wasn’t talking about internal functions… I’m talking about userland code in the hypothetical case that we added strict-only hints.
I don’t see where you’ve gotten that impression from.
Well ... existing userland code doesn't have scalar type hints, it
couldn't possibly do. How can you have migration issues with it?I’ll just quote my previous message:
One of the nice things about strict mode only applying to code which asks for it, is that if a function if an API has type hints added, it won’t suddenly break calling code that didn’t strictly match types, if that calling code uses the default weak mode behaviour (which it will if it was written pre-PHP 7).
For example, say I have some sort of Response object that lets you set a body:
class Response {
public function setBody($message);
}In PHP 5, it’s perfectly fine to pass something that’s not a string for $message:
$foo = new Response;
$foo->setBody(67);Absurd example, but this sort of thing does happen in real world code, often accidentally.
Now, let’s say we add a string type hint in a new version of the library:
interface Response {
public function setBody(string $message);
}If PHP’s type hints were always strict, then our existing PHP 5 code from earlier that took advantage of PHP’s weak typing would now produce an error:
Catchable fatal error: Argument 1 passed to Response::setBody() must be of the type string, integer given
This isn’t good - it makes migration of the existing codebase difficult.
Weak typing solves this problem because it allows conversions. However, it’s not really good that the code was passing an integer in the first place - it should really be passing a string.
The solution, then, is what this RFC offers. By default, weak typing is used, so your existing code doesn’t break initially. But once you’ve added type hints in a few places, you can switch to strict typing, and that error will be detected and can be fixed.
This way, we can have stricter types without sacrificing compatibility or complicating migration.
Basically, strict-only types complicates their addition to existing codebases, including libraries.
What this RFC proposes is similar to Hack’s gradual typing, in a sense, in that it allows you to gradually add types to your codebase without breaking things.
Eh ... sorry for not mentioning that in the same mail, but I've never
suggested a strict-only approach.
Cheers,
Andrey.
As I already told, in my opinion, version 0.1 was the perfect solution that
fit into PHP semantic very well.declare(strict_types=1); - is really weird solution.
It changes type hinting behavior per file scope, so, just to try strict
type hinting in a big project, people will have to change every single PHP
file.
declare() might not be beautiful, but it is pragmatic as it already exists.
As for full project switch, can’t we easily do a followup RFC with a command line flag/ini setting to run unit tests in strict mode for instance?
THis is why I believe it makes more sense to have this switch on the
callee side, instead of on the calling side.
I’m not sure I see why that would make more sense.
On the callee side what you get is strictly what you asked for anyway, no matter what mode on the calling side.
This is the true beauty of what Andrea has come up with here, allowing weak PHP like forgiveness to co-exists with opt in for strict behavior.
Best,
André
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
I think v0.1 had pretty good chances to get accepted, but I’m not so sure about anything that followed.
I’m definitely -1 on declare(strict).
Regards,
Mike
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
I think v0.1 had pretty good chances to get accepted, but I’m not so sure about anything that followed.
I’m definitely -1 on declare(strict).
I agree. I understand that someone might prefer strict typing, but
declare() seems so different from anything else in php. I think I've
only used it when I needed signal handling and even in that case it felt
so weird.
Cheers
Matteo Beccati
Development & Consulting - http://www.beccati.com/
I think v0.1 had pretty good chances to get accepted, but I’m not so
sure about anything that followed.
I’m definitely -1 on declare(strict).I agree. I understand that someone might prefer strict typing, but
declare() seems so different from anything else in php. I think I've
only used it when I needed signal handling and even in that case it felt
so weird.
Add to that 'E_STRICT' ... just what is the preferred way of doing things?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
what about giving several voting options? yes/no for scalar type hints and yes/no for declare-strict
Regards
Thomas
Michael Wallner schrieb am 2. Feb 2015 09:49:
Good evening,
The RFC has been updated to cover return types, since Levi’s Return
Types RFC has passed. The patch is a work in progress: it works, but
lacks tests for return types.Version 0.3 of the RFC can be found here:
https://wiki.php.net/rfc/scalar_type_hintsI think v0.1 had pretty good chances to get accepted, but I’m not so
sure about anything that followed.
I’m definitely -1 on declare(strict).Regards,
Mike
Hello Andrea,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
although my involvement here is very sparse at the moment, please let me
tell you that I a) find it great that you don't give up, are
persistently going for your idea while b) still being objective rather
then emotional. I'm really happy to see such technical, lively
discussion you initiated so far. Thank you :-)
That said ...
-
I dislike the RFC since the introduction of the declare() adaption
(effectively 0.2/0.3 now) and did not 100% agree with 0.1 -
Since consensus on the strict mode does part the community (or, the
greater community also outside @internals) my impression is that the
current best way to move forward would be -
get the rfc to only go for weak types for now
-
using the "cast-like syntax": function foo( (int) $bar );
and ultimately keep the strict type out for /now/ and try it at a later
time, the "function foo( int $bar )"-syntax.
I'm actually not really in favor of just weak types, I would consider
myself a "strict type" voter, but through the community communication
here I saw a) the benefits of weak types hinting/casting b) without
getting in the way of a possible future strict type (e.g. with the
"non-cast-like syntax").
thank you,
- Markus
Hi Markus,
Since consensus on the strict mode does part the community (or, the
greater community also outside @internals) my impression is that the
current best way to move forward would beget the rfc to only go for weak types for now
using the "cast-like syntax": function foo( (int) $bar );
and ultimately keep the strict type out for /now/ and try it at a later
time, the "function foo( int $bar )"-syntax.
I’m not sure that really works that well. It’s not a terribly good compromise: If you want strict typing, you not only haven’t got it, but even worse, you’ll be forced to deal with weak typing if you use the wrong library, because the (int) syntax would be specifically for weak types. It’s not really a compromise at all, actually.
I'm actually not really in favor of just weak types, I would consider
myself a "strict type" voter, but through the community communication
here I saw a) the benefits of weak types hinting/casting b) without
getting in the way of a possible future strict type (e.g. with the
"non-cast-like syntax”).
Well this RFC tries to strike a different balance: rather than having the chaos of some functions using weak types, others strict types, others both, it just adds scalar types and lets you choose the behaviour that suits you. It means weak typing fans can live in their weakly-typed world, and strict typing fans can live in their strictly-typed world. That’s the idea, anyway.
But I’m just going in circles at this point. :P
Thanks for your contributions.
--
Andrea Faulds
http://ajf.me/
Hi,
Hi Markus,
Since consensus on the strict mode does part the community (or, the
greater community also outside @internals) my impression is that the
current best way to move forward would beget the rfc to only go for weak types for now
using the "cast-like syntax": function foo( (int) $bar );
and ultimately keep the strict type out for /now/ and try it at a later
time, the "function foo( int $bar )"-syntax.I’m not sure that really works that well. It’s not a terribly good compromise: If you want strict typing, you not only haven’t got it, but even worse, you’ll be forced to deal with weak typing if you use the wrong library, because the (int) syntax would be specifically for weak types. It’s not really a compromise at all, actually.
I'm actually not really in favor of just weak types, I would consider
myself a "strict type" voter, but through the community communication
here I saw a) the benefits of weak types hinting/casting b) without
getting in the way of a possible future strict type (e.g. with the
"non-cast-like syntax”).Well this RFC tries to strike a different balance: rather than having the chaos of some functions using weak types, others strict types, others both, it just adds scalar types and lets you choose the behaviour that suits you. It means weak typing fans can live in their weakly-typed world, and strict typing fans can live in their strictly-typed world. That’s the idea, anyway.
But I’m just going in circles at this point. :P
If chaos is what you call it - we want chaos. :P
Cheers,
Andrey.
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
After thinking and talking this over, I do think your RFC is the only
option that makes sense if you want to support both weak and strict.
However, I think the usage of declare() makes it dead in the water.
Fair or not, I have a hard time looking past that.
I'm opposed to other compromises because I think it will be a big mess
from the caller's perspective. (Some functions would be strict, some
would not ... eventually forcing everybody to just use strict types.)
And, as I've stated previously, I prefer strict types.
Does the implementation of strict-only work for testing right now? (If
so, what branch is it on, etc?) It's easy for everybody to theorize
about how this would work, but why not actually take the time to
"strictify" some part of a commonly used library and see how it
actually works in practice? But a library with type-hints + a script
to prepend "use strict" to every PHP file would make testing impact on
real-world usage easy for anybody.
--
Matthew Leverton
Hi Matthew,
Good evening,
The RFC has been updated to cover return types, since Levi’s Return Types RFC has passed. The patch is a work in progress: it works, but lacks tests for return types.
Version 0.3 of the RFC can be found here: https://wiki.php.net/rfc/scalar_type_hints
After thinking and talking this over, I do think your RFC is the only
option that makes sense if you want to support both weak and strict.
However, I think the usage of declare() makes it dead in the water.
Fair or not, I have a hard time looking past that.
Ah, that’s unfortunate. I know declare() is ugly and a little unwieldy, but I can’t see another way to do it which doesn’t cause bigger problems. I am convinced that if this RFC passed, people would probably get used to declare(). IDEs and command-line tools do exist.
I'm opposed to other compromises because I think it will be a big mess
from the caller's perspective. (Some functions would be strict, some
would not ... eventually forcing everybody to just use strict types.)
And, as I've stated previously, I prefer strict types.
That’s how I feel as well.
Does the implementation of strict-only work for testing right now? (If
so, what branch is it on, etc?) It's easy for everybody to theorize
about how this would work, but why not actually take the time to
"strictify" some part of a commonly used library and see how it
actually works in practice? But a library with type-hints + a script
to prepend "use strict" to every PHP file would make testing impact on
real-world usage easy for anybody.
The implementation does work for testing. I still need to write tests for return types but they seem to work. Parameter types are fully-working, though, and they have extensive tests, so I know they’re working fine and you could add them to an existing project.
Strictifying an existing library is a good idea. I’ll try “strictifying” one of my bigger personal projects (PictoSwap, a 3DS browser application with a PHP backend) and see how it goes. I expect it’ll be fairly smooth, we’ll see.
Thanks for your thoughts.
Andrea Faulds
http://ajf.me/
Hey everyone,
The implementation does work for testing. I still need to write tests for return types but they seem to work. Parameter types are fully-working, though, and they have extensive tests, so I know they’re working fine and you could add them to an existing project.
Strictifying an existing library is a good idea. I’ll try “strictifying” one of my bigger personal projects (PictoSwap, a 3DS browser application with a PHP backend) and see how it goes. I expect it’ll be fairly smooth, we’ll see.
I just went and did this on PictoSwap, it was fairly painless. It’s quite a small application, to be fair, but it is “real-world code”.
First, I compiled my branch with the following configure command:
YACC=/usr/local/opt/bison27/bin/bison ./configure --enable-debug --enable-phpdbg --disable-all --with-gd --enable-pdo --with-sqlite3 --with-pdo-sqlite --enable-session --enable-json
Ignore the YACC=, I only need to do that because OS X is weird. As you can see, PictoSwap requires Gd, PDO-SQLite, Session and JSON.
Then, I ran my site with the freshly-compiled version of PHP. Actually, that’s not quite true - I compiled several times, each time finding an error because of a missing extension. Eventually I got to this configure line which included all the ones my app needed.
Second, I added declare(strict_types=1); to each file along with type hints. I did this file by file, and tested with each file.
For most of the files, nothing was broken by the addition of strict type hints. However, some files did cause issues.
When I added hints to my graphics functions in include/graphics.php and turned on strict types, I got an error because of a type mismatch, which lead to me discovering a bug. It turns out I’d been assuming that gd takes float pixel positions, but it actually takes integer pixels! This means that those crucial .5s had been truncated off all this time, and I was none-the-wiser. I added explicit integer casts. Now it’s obvious that the results are being truncated.
Adding strict hints to include/user.php, which includes the “business logic” as such turned up the most issues. It showed me a few different things.
One thing I learned was that return types are crippled by the lack of nullable returns. For most of my functions, I need to return TRUE
(success) or a string (error message). I’d be fine with switching to NULL
(success) or string (error) so it’s hintable, but I can’t actually do that, because we lack nullable returns. That means I’m omitting return types on most of my functions, unfortunately. I hope that the Nullable Types RFC can pass and fix this.
Another thing I learned was how I really needed to convert the values going into and coming out of my database (SQLite 3, in this case). Turns out most of the data in there was strings, as SQLite is dynamically-typed, and so my JSON output was ending up filled with strings, where it should have had numbers or booleans. Type mismatch errors allowed me to spot where this was happening. It’s only because JavaScript is similarly merciful to PHP that my web app worked at all!
I also learned that my session data didn’t have correct types: the user ID had ended up a string, not an integer. This was trivially fixed, but something I wouldn’t have noticed without strict typing.
Now, the addition of type hints to include/user.php broke my web-facing code (htdocs/api.php), because I wasn’t converting types properly. However, this only broke it when it used strict typing mode. If I turned off strict typing mode, as I expected, PHP happily converted the types and everything worked swimmingly. The fixes weren’t that difficult, but not having to make everything strict at once made adding type hints easier, because I could disable strict types in code that wasn’t yet ready and my app would keep running fine, then turn on strict types one it was updated.
The end result of this was better code, and I spotted some errors. The migration was eased, as I had hoped, by the ability to make some files strict and others weak.
It also shows that my web app works fine without modifications on PHP 7, which is great.
Admittedly, my web app is quite small. But I think this makes a good case for the usefulness of this RFC, and in particular of the declare() system, and strict hints vs. weak hints. :)
You can see the diff here: https://github.com/TazeTSchnitzel/PictoSwap/compare/php7-strict
Thanks!
Andrea Faulds
http://ajf.me/
Hi Andrea,
In you proposal you disable declaration of classes with names, that may be
used for scalar type hints - Int, Float, ...
What do you think about using only lowercase type names for scalar type
hints?
In this case we won't have to introduce any limitations.
function foo(int $a) // expects integer
function foo(Int $a) // expects instance of class Int
Thanks. Dmitry.
Hey everyone,
The implementation does work for testing. I still need to write tests
for return types but they seem to work. Parameter types are fully-working,
though, and they have extensive tests, so I know they’re working fine and
you could add them to an existing project.Strictifying an existing library is a good idea. I’ll try “strictifying”
one of my bigger personal projects (PictoSwap, a 3DS browser application
with a PHP backend) and see how it goes. I expect it’ll be fairly smooth,
we’ll see.I just went and did this on PictoSwap, it was fairly painless. It’s quite
a small application, to be fair, but it is “real-world code”.First, I compiled my branch with the following configure command:
YACC=/usr/local/opt/bison27/bin/bison ./configure --enable-debug
--enable-phpdbg --disable-all --with-gd --enable-pdo --with-sqlite3
--with-pdo-sqlite --enable-session --enable-jsonIgnore the YACC=, I only need to do that because OS X is weird. As you can
see, PictoSwap requires Gd, PDO-SQLite, Session and JSON.Then, I ran my site with the freshly-compiled version of PHP. Actually,
that’s not quite true - I compiled several times, each time finding an
error because of a missing extension. Eventually I got to this configure
line which included all the ones my app needed.Second, I added declare(strict_types=1); to each file along with type
hints. I did this file by file, and tested with each file.For most of the files, nothing was broken by the addition of strict type
hints. However, some files did cause issues.When I added hints to my graphics functions in include/graphics.php and
turned on strict types, I got an error because of a type mismatch, which
lead to me discovering a bug. It turns out I’d been assuming that gd takes
float pixel positions, but it actually takes integer pixels! This means
that those crucial .5s had been truncated off all this time, and I was
none-the-wiser. I added explicit integer casts. Now it’s obvious that the
results are being truncated.Adding strict hints to include/user.php, which includes the “business
logic” as such turned up the most issues. It showed me a few different
things.One thing I learned was that return types are crippled by the lack of
nullable returns. For most of my functions, I need to returnTRUE
(success)
or a string (error message). I’d be fine with switching toNULL
(success)
or string (error) so it’s hintable, but I can’t actually do that, because
we lack nullable returns. That means I’m omitting return types on most of
my functions, unfortunately. I hope that the Nullable Types RFC can pass
and fix this.Another thing I learned was how I really needed to convert the values
going into and coming out of my database (SQLite 3, in this case). Turns
out most of the data in there was strings, as SQLite is dynamically-typed,
and so my JSON output was ending up filled with strings, where it should
have had numbers or booleans. Type mismatch errors allowed me to spot where
this was happening. It’s only because JavaScript is similarly merciful to
PHP that my web app worked at all!I also learned that my session data didn’t have correct types: the user ID
had ended up a string, not an integer. This was trivially fixed, but
something I wouldn’t have noticed without strict typing.Now, the addition of type hints to include/user.php broke my web-facing
code (htdocs/api.php), because I wasn’t converting types properly. However,
this only broke it when it used strict typing mode. If I turned off strict
typing mode, as I expected, PHP happily converted the types and everything
worked swimmingly. The fixes weren’t that difficult, but not having to make
everything strict at once made adding type hints easier, because I could
disable strict types in code that wasn’t yet ready and my app would keep
running fine, then turn on strict types one it was updated.The end result of this was better code, and I spotted some errors. The
migration was eased, as I had hoped, by the ability to make some files
strict and others weak.It also shows that my web app works fine without modifications on PHP 7,
which is great.Admittedly, my web app is quite small. But I think this makes a good case
for the usefulness of this RFC, and in particular of the declare() system,
and strict hints vs. weak hints. :)You can see the diff here:
https://github.com/TazeTSchnitzel/PictoSwap/compare/php7-strictThanks!
Andrea Faulds
http://ajf.me/
Am 04.02.2015 um 06:44 schrieb Dmitry Stogov:
What do you think about using only lowercase type names for scalar type
hints? In this case we won't have to introduce any limitations.
This would be inconsistent with the rest of PHP being case-insensitive
and only lead to confusion.
Hi Dmitry and Sebastian,
Am 04.02.2015 um 06:44 schrieb Dmitry Stogov:
What do you think about using only lowercase type names for scalar type
hints? In this case we won't have to introduce any limitations.This would be inconsistent with the rest of PHP being case-insensitive
and only lead to confusion.
This is how I feel. Array and Callable work, yet if Integer and String didn’t it’d be inconsistent.
Also, we’d still have a BC issue, because who says that people with String classes didn’t use a lowercase type hint?
I think the BC cost, while unfortunate, is unavoidable. Luckily, code can be changed in such a way that it’ll keep working fine on PHP 5 and only break on PHP 7, by using class_alias()
.
Thanks.
Andrea Faulds
http://ajf.me/
Le 14/01/2015 01:16, Andrea Faulds a écrit :
Good evening,
I’ve made some quite significant changes to my Scalar T ype Hints RFC, and bumped its version to 0.2.
Here: https://wiki.php.net/rfc/scalar_type_hints
This is a new thread because I’ve made a significant revision to the RFC, so it’d be sensible to separate discussion of the updated RFC from the v0.1 RFC.
Please tell me your thoughts.
Thanks!
Hi Andrea,
I am probably going to ask a stupid question, but do we really need the
=1 part in declare?
declare(strict_types=1) couldn't be declare(strict_types)?
Or does it mean that there would be cases when strict typing would be
deactivated after being activated with declare(strict_types=0)?
To be honest, I don't like declare() because it looks like a function
call, not a setting for the file like a namespace declaration would be.
Also, in the case of declare(ticks=1), 1 is not a boolean but an
interval so I find it a bit confusing that strict_types=1 would be a
boolean in that case. Or maybe declare(strict_types=true) then?
Personnally I would prefer a syntax like:
declare strict;
which is just shorter and more readable in my opinion. I know it is
mostly cosmetic but I don't really understand why declare uses
parenthesis if it is a language construct and not a function (and yes, I
think that declare(ticks=1) also looks silly ;) );
So basically instead of that at the top of my files:
<?php
namespace Foo;
use Bar;
declare(strict_types=1);
I would prefer having that:
<?php
namespace Foo;
use Bar;
declare strict;
It's probably a detail in the whole discussion, but for some weird
psychological reason, it matters to me :),
Cheers,
Pascal
Hi Pascal,
I am probably going to ask a stupid question, but do we really need the =1 part in declare?
declare(strict_types=1) couldn't be declare(strict_types)?
Or does it mean that there would be cases when strict typing would be deactivated after being activated with declare(strict_types=0)?
Oh, I made it like that because that’s the existing syntax of declare(), it takes a name and a value. But I suppose it could be modified to allow just a name. I don’t think we should modify it just for this specific case, really… less exceptions to a rule and more consistency are generally a good thing.
There is a use for declare(strict_types=0), which is to make part of a file weak while having the rest strict. It’s not something you’d want to do very often, but it may be useful in some rare cases. If we have declare(strict_types=1), then it makes sense to also have declare(strict_types=0). It’d be rather odd to not allow it.
To be honest, I don't like declare() because it looks like a function call, not a setting for the file like a namespace declaration would be. Also, in the case of declare(ticks=1), 1 is not a boolean but an interval so I find it a bit confusing that strict_types=1 would be a boolean in that case. Or maybe declare(strict_types=true) then?
I originally had it be a boolean, but considering how often this would be used, I changed it to 1 for terseness. Using 1 is common for INI settings, so I don’t think it’d be that confusing, but I see your point.
Personnally I would prefer a syntax like:
declare strict;which is just shorter and more readable in my opinion. I know it is mostly cosmetic but I don't really understand why declare uses parenthesis if it is a language construct and not a function (and yes, I think that declare(ticks=1) also looks silly ;) );
So basically instead of that at the top of my files:
<?php
namespace Foo;
use Bar;
declare(strict_types=1);I would prefer having that:
<?php
namespace Foo;
use Bar;
declare strict;It's probably a detail in the whole discussion, but for some weird psychological reason, it matters to me :),
I can see the appeal, though I’m not really sure about adding new syntax just for this.
By the way, I think declare() would be easily distinguished from a function for two reasons. Firstly, you can’t assign to constants, and secondly, it’ll be syntax-highlights differently.
I can understand your concerns, though. :)
Thanks for voicing them.
Andrea Faulds
http://ajf.me/