Hello,
I came across some info on the web that states that scalar type hinting was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?
I know PHP is considered to be a weak typed language but it should also be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.
Best regards,
__
Raymond
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the discussion
has quieted for the moment.
I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.
--Kris
Hello,
I came across some info on the web that states that scalar type hinting was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond
Hi,
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.
Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_types
Bye
Simon
2012/3/6 Kris Craig kris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
Hello,
I came across some info on the web that states that scalar type hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also
be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond
My concern is the total lack of talk on-list about it. It's obviously
not perfect, but there has been little to no talk on-list about it.
That is an indication to me that it's not ready or that it won't get
in if put to a vote...
Thoughts?
Anthony
On Tue, Mar 6, 2012 at 6:10 PM, Simon Schick
simonsimcity@googlemail.com wrote:
Hi,
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_typesBye
Simon2012/3/6 Kris Craig kris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
Hello,
I came across some info on the web that states that scalar type hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also
be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond
Personally, speaking for myself at least, I've quieted on the subject
temporarily in favor of advocating some improvements to the RFC voting
process that will ultimately make it easier for us to work through these
type hinting questions. I'll be resurrecting the discussion on this end
before too long. =)
--Kris
My concern is the total lack of talk on-list about it. It's obviously
not perfect, but there has been little to no talk on-list about it.
That is an indication to me that it's not ready or that it won't get
in if put to a vote...Thoughts?
Anthony
On Tue, Mar 6, 2012 at 6:10 PM, Simon Schick
simonsimcity@googlemail.com wrote:Hi,
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_typesBye
Simon2012/3/6 Kris Craig kris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the
discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though
some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
On Mon, Mar 5, 2012 at 6:20 PM, Raymond Irving xwisdom@gmail.com
wrote:Hello,
I came across some info on the web that states that scalar type
hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because
of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should
also
be
about freedom. Freedom for a PHP developer to choose to use scalar
type
hinting whenever he/she sees the need.Best regards,
__
Raymond
My concern is the total lack of talk on-list about it. It's obviously
not perfect, but there has been little to no talk on-list about it.
That is an indication to me that it's not ready or that it won't get
in if put to a vote...Thoughts?
I really like the proposal you set forth. I have zero clue what impact
it would have on performance, however, so I'm deferring that discussion
to those who do.
As a user and framework developer, I'd love to see it in place --
casting support at the function/method parameter level would greatly
simplify a lot of code I write.
On Tue, Mar 6, 2012 at 6:10 PM, Simon Schick
simonsimcity@googlemail.com wrote:Hi,
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_typesBye
Simon2012/3/6 Kris Craig kris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
Hello,
I came across some info on the web that states that scalar type hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also
be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond
--
Matthew Weier O'Phinney
Project Lead | matthew@zend.com
Zend Framework | http://framework.zend.com/
PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc
Hi!
Just took a look on it - the syntax proposed there is quite ugly and
rather confusing, I really wouldn't like to have such syntax in PHP.
Also "(int) $foo = “1” will generate an E_COMPILE_ERROR" makes no sense
to me.
Also, this line:
function test((int) $intParam, (string) $strParam = "foo", (array)
$array) {}
is not proper PHP code - it contains optional parameter and then
parameter with no default.
And can we please stop using word "hinting"?
We can call it type conversion, typecasting, type coercion, etc.
http://en.wikipedia.org/wiki/Type_conversion
But I don't see how there's any hinting involved.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Stas Malyshev wrote:
And can we please stop using word "hinting"?
We can call it type conversion, typecasting, type coercion, etc.
http://en.wikipedia.org/wiki/Type_conversionBut I don't see how there's any hinting involved.
Is this were things have drifted from the original working base? I was under the
impression that the idea was to give developers a nudge as to what type of
parameter was required ( so documentation did the job for me ) rather than
forcing a conversion when the wrong type was supplied?
Which particular problem is being worked on?
--
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//
Firebird - http://www.firebirdsql.org/index.php
Hi,
I'm with Stas here.
First let me say that I would like to see type hinting for scalars in
PHP. As a userland developer it would help me to write clean and more
robust code. But I think this proposal is only a workaround to get a
round the main problem. It's a try to push similar functionality into
PHP without breaking BC. I think it's the wrong way.
Anthony, You addressed one of the main issues in your last post.
Again, I personally see casting data-loss a bigger issue than just
parameter hinting, which should get its own RFC to clean up. That's
why I didn't include it here. On purpose...
Why not try to change this first?
I know there are more issues to solve. But I think only solving issue
piece by piece, regardless if BC breaks, brings a robust and clean
implementation of this feature. Not immediately, maybe in the next major
version.
Just my 2 cents.
Christian
Am 07.03.2012 08:31, schrieb Stas Malyshev:
Hi!
Just took a look on it - the syntax proposed there is quite ugly and
rather confusing, I really wouldn't like to have such syntax in PHP.
Also "(int) $foo = “1” will generate an E_COMPILE_ERROR" makes no
sense to me.
Also, this line:
function test((int) $intParam, (string) $strParam = "foo", (array)
$array) {}is not proper PHP code - it contains optional parameter and then
parameter with no default.And can we please stop using word "hinting"?
We can call it type conversion, typecasting, type coercion, etc.
http://en.wikipedia.org/wiki/Type_conversionBut I don't see how there's any hinting involved.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Christian,
On Wed, Mar 7, 2012 at 3:22 AM, Christian Kaps
christian.kaps@mohiva.com wrote:
Hi,
I'm with Stas here.
First let me say that I would like to see type hinting for scalars in PHP.
As a userland developer it would help me to write clean and more robust
code. But I think this proposal is only a workaround to get a round the main
problem. It's a try to push similar functionality into PHP without breaking
BC. I think it's the wrong way.
Again, the lack of a BC break is a side-effect of the main limiting
factor which was to allow for stricter checks in the future and keep
some semblance of a sensible syntax (having foo(int $foo) allow
foo("5") makes a lot less sense to me)...
Anthony, You addressed one of the main issues in your last post.
Again, I personally see casting data-loss a bigger issue than just
parameter hinting, which should get its own RFC to clean up. That's why I
didn't include it here. On purpose...Why not try to change this first?
The simple reason, is that I was under the impression that one or more
devs were writing that proposal. I was going to let them. If they
have stopped, or want my help, or want me to do it, I'm all for
that...
Thanks,
Anthony
I, for one, decided not to participate in the discussions any more
because they always change to something different in a few hours of
discussion. I'm surprised how people tend to complicate the feature
into something weird and ugly. I now understand why core team just
ignores some discussions.
I don't like the function a( (int) $int) syntax and approach - it's
not type hinting, it's auto-converting arguments. And adding function
a( (array) $array) is just, well, pointless. Why? Because if you have
a conversion from scalar to array - you definitely have something
wrong in the code that needs fixing, not converting and continue to
run the code like it's OK. It should come like a barrier, not a
filter. And current array and object type hinting does just that. The
(object) is also pointless for type hinting. Why? Because you usually
expect not any damn object, but an object of certain type and it's
children. That works now just fine and errors the hell out if
something isn't right.
I realize that with scalars it's not that straight forward, but
complicating things by adding an auto-cast syntax and so on is just
ridiculous. Hints should stay, well, hints. The only problem we have
is complications of accepting numerical strings or numbers as strings.
And what to do with "null". Everything else is irrelevant.
function a(bool $bool) {}
a(10); // Kill your self against the wall - write a(true);
If you define bool - use the damn bool! It's not an "if" or "switch"
statement where auto-converting is usually used. It's a function call,
you should pass to it correct arguments. Type hinting is working only
for more internal API's - the data filtering and validating layer
using type hints will generate errors all over the place. We all know
how many security hole scanners out there that scan sites and pass all
kind of data to our scripts to break them and try exploiting that.
I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Type hinting is not for using it all over the place - it should be
used in places it is really needed. And it should define the expected
type with some auto-converting limited special cases like I have
written above. That is really all it needs. No
super-duper-auto-converting type-hints, no variable type hinting and
other wild stuff I have seen during last 2-3 weeks.
Anything more complicated than that and count a -1 vote from me.
Hi Arvids,
I pretty much like this idea as it's more strict. Let me say something
to the questions you pointed out here.
2012/3/7 Arvids Godjuks arvids.godjuks@gmail.com:
I realize that with scalars it's not that straight forward, but
complicating things by adding an auto-cast syntax and so on is just
ridiculous. Hints should stay, well, hints. The only problem we have
is complications of accepting numerical strings or numbers as strings.
And what to do with "null".
I'd like to handle it the same way as it's handled with the classes
right now. If null is not the default-value you'll get an error when
you pass null in there.
One thing I'd like opened here: If you define a default-value
different than null, should you be able to pass null as well and the
compiler will use the default-value?
function a(bool $bool) {}
a(10); // Kill your self against the wall - write a(true);
If you define bool - use the damn bool!
I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.
I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Until now I thought about the weak variable-types as a order ...
string, float, integer, Boolean.
All Boolean values are compatible be an integer (0 or 1) and all
integer are compatible to a float and so on. Do you think it's good to
have it this way? This would mean that you could also get a Boolean
true as string "1" ... I personally don't like that ... but I don't
know where to draw the strict-line.
Now think about that backwards. Can a "1" be passed as a parameter
that expects Boolean? If yes, I'd keep it consistent in both ways.
Bye
Simon
Hi,
Just a small addition to what I wrote about handling null ...
function foo(array $d = array()) { var_dump($d); }
foo(null); // This fails with the message: Argument 1 passed to foo()
must be an array, null given
As this code fails I'd not expect to change this behavior for the weak-types.
function foo(int $d = 20) { var_dump($d); }
foo(null); // This should then also fail. Don't care about what's the
default-value.
Bye
Simon
2012/3/8 Simon Schick simonsimcity@googlemail.com:
Hi Arvids,
I pretty much like this idea as it's more strict. Let me say something
to the questions you pointed out here.2012/3/7 Arvids Godjuks arvids.godjuks@gmail.com:
I realize that with scalars it's not that straight forward, but
complicating things by adding an auto-cast syntax and so on is just
ridiculous. Hints should stay, well, hints. The only problem we have
is complications of accepting numerical strings or numbers as strings.
And what to do with "null".I'd like to handle it the same way as it's handled with the classes
right now. If null is not the default-value you'll get an error when
you pass null in there.
One thing I'd like opened here: If you define a default-value
different than null, should you be able to pass null as well and the
compiler will use the default-value?function a(bool $bool) {}
a(10); // Kill your self against the wall - write a(true);
If you define bool - use the damn bool!I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Until now I thought about the weak variable-types as a order ...
string, float, integer, Boolean.
All Boolean values are compatible be an integer (0 or 1) and all
integer are compatible to a float and so on. Do you think it's good to
have it this way? This would mean that you could also get a Boolean
true as string "1" ... I personally don't like that ... but I don't
know where to draw the strict-line.
Now think about that backwards. Can a "1" be passed as a parameter
that expects Boolean? If yes, I'd keep it consistent in both ways.Bye
Simon
From: Simon Schick [mailto:simonsimcity@googlemail.com]
I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Until now I thought about the weak variable-types as a order ...
string, float, integer, Boolean.
All Boolean values are compatible be an integer (0 or 1) and all
integer are compatible to a float and so on. Do you think it's
good to have it this way? This would mean that you could also get
a Boolean true as string "1" ... I personally don't like that ...
but I don't know where to draw the strict-line.
Now think about that backwards. Can a "1" be passed as a parameter
that expects Boolean? If yes, I'd keep it consistent in both ways.Bye
Simon
Conversion the other way is essential. Consider the following URL:
In your PHP script $_GET['foo'] === '1' (a string).
In fact, nearly every input to PHP is a string. This is why PHP was designed with some seriously robust type juggling on scalars. Any typing proposal that wants to actually pass a vote is going to have to allow appropriate implicit conversions from string to other types.
John Crenshaw
Priacta, Inc.
In fact, nearly every input to PHP is a string. This is why PHP was
designed with some seriously robust type juggling on scalars. Any
typing proposal that wants to actually pass a vote is going to have
to allow appropriate implicit conversions from string to other
types.
In fact, nearly every output from PHP is a string. Also why PHP was
designed with some seriously robust type juggling on scalars. Any
typing proposal that wants to actually pass a vote is going to have to
allow appropriate implicit conversions to string from other types.
$x = 1.8;
$y = 2.3;
list( $int, $fract ) = explode( '.', $x + $y );
2012/3/8 John Crenshaw johncrenshaw@priacta.com:
Conversion the other way is essential. Consider the following URL:
In your PHP script $_GET['foo'] === '1' (a string).
In fact, nearly every input to PHP is a string. This is why PHP was designed with some seriously robust type juggling on scalars. Any typing proposal that wants to actually pass a vote is going to have to allow appropriate implicit conversions from string to other types.
John Crenshaw
Priacta, Inc.
Hi, John
Ok .. the example with the get-parameter is quite good.
You'll often have the case that you submit a string "0" or "1" and
want to have it as boolean (f.e. if you have a dropdown with two
options).
Please keep in mind not to mix it up with checkboxes as unchecked
checkboxes won't be sent back to your webserver :)
Bye
Simon
Hi Simon!
2012/3/8 Simon Schick simonsimcity@googlemail.com:
Hi Arvids,
I pretty much like this idea as it's more strict. Let me say something
to the questions you pointed out here.2012/3/7 Arvids Godjuks arvids.godjuks@gmail.com:
I realize that with scalars it's not that straight forward, but
complicating things by adding an auto-cast syntax and so on is just
ridiculous. Hints should stay, well, hints. The only problem we have
is complications of accepting numerical strings or numbers as strings.
And what to do with "null".I'd like to handle it the same way as it's handled with the classes
right now. If null is not the default-value you'll get an error when
you pass null in there.
One thing I'd like opened here: If you define a default-value
different than null, should you be able to pass null as well and the
compiler will use the default-value?function a(bool $bool) {}
a(10); // Kill your self against the wall - write a(true);
If you define bool - use the damn bool!I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.
I think "Catchable fatal error should" be fine and users are familiar
with such mechanic because it already exists. Consistency, man,
consistency :)
I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Until now I thought about the weak variable-types as a order ...
string, float, integer, Boolean.
All Boolean values are compatible be an integer (0 or 1) and all
integer are compatible to a float and so on. Do you think it's good to
have it this way? This would mean that you could also get a Boolean
true as string "1" ... I personally don't like that ... but I don't
know where to draw the strict-line.
Now think about that backwards. Can a "1" be passed as a parameter
that expects Boolean? If yes, I'd keep it consistent in both ways.Bye
Simon
That's a good tricky question, I like it.
Well, I think the lower should work just fine.
function a(bool $int) {};
a("1");
Because it's conversion to bool is straight forward. What of the
integer values [-∞, -1] and [2, +∞]? Really tricky question. From one
point of view they are a valid boolean true in the expressions. But
the question here is not if it's a valid boolean, but the fact that we
want our function to be passed with valid data and be more strict that
usual on what is passed to the function/method. So I would like to see
valid boolean values for a hinted argument these:
true
false
1
0
"1"
"0"
Simple and clear.
2012/3/8 Simon Schick simonsimcity@googlemail.com:
Hi,
Just a small addition to what I wrote about handling null ...
function foo(array $d = array()) { var_dump($d); }
foo(null); // This fails with the message: Argument 1 passed to foo()
must be an array, null givenAs this code fails I'd not expect to change this behavior for the weak-types.
function foo(int $d = 20) { var_dump($d); }
foo(null); // This should then also fail. Don't care about what's the
default-value.Bye
Simon
Totally agree here.
I would even say that if you need a null as default value - that
can't be a type hinted argument, because it already has to accept two
different types of data and code inside has to handle that anyway. The
type hint is essentially useless in this situation. Adding something
like function a(null|string $a = null) kind'a silly and again is
adding unneeded complexity.
2012/3/8 Simon Schick simonsimcity@googlemail.com:
2012/3/8 John Crenshaw johncrenshaw@priacta.com:
Conversion the other way is essential. Consider the following URL:
In your PHP script $_GET['foo'] === '1' (a string).
In fact, nearly every input to PHP is a string. This is why PHP was designed with some seriously robust type juggling on scalars. Any typing proposal that wants to actually pass a vote is going to have to allow appropriate implicit conversions from string to other types.
John Crenshaw
Priacta, Inc.Hi, John
Ok .. the example with the get-parameter is quite good.
You'll often have the case that you submit a string "0" or "1" and
want to have it as boolean (f.e. if you have a dropdown with two
options).
Please keep in mind not to mix it up with checkboxes as unchecked
checkboxes won't be sent back to your webserver :)Bye
Simon
This is exactly the example for witch type hinting should not be used.
$_GET and $_POST data can be anything - string, number, array (lord,
how many scripts break into fatal errors when you just pass an array
instead of simple string). And passing data from these sources as
params to type hinted functions is a suicide. Type hints are meant to
filter input from external sources - that data should be passed
through filtering and validating layer - only after this you can work
with the data and passing it to type hinted methods and functions.
So I will remind to every one: Type hinting is not a filtering layer.
This is an instrument for designing a more strict internal layer and
prevent people passing unfiltered and insecure data to that layer. It
also helps to track the errors in code where invalid data slips
through the cracks. It also helps with the future optimization,
documentation generation and reflection. It does not mean that you can
now write only type hinted code - you can't and you shouldn't even try
(that will only make things unnecessary hard).
I have a very good relationship with array and object type hints right
now - they are used in a few key places, but their usage relative to
the whole application is not very wide. Same I imagine for the scalar
hints.
Type hints are meant to
filter input from external sources
Correction, it should read like this:
Type hints are not meant to filter input from external sources
From: Arvids Godjuks [mailto:arvids.godjuks@gmail.com]
I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.I think "Catchable fatal error should" be fine and users are familiar with such mechanic because it already exists. Consistency, man, consistency :)
Yeah, I was a huge advocate of this too until recently. I've changed my mind though, ironically enough to ensure better consistency.
PHP since 5.3 gives an E_WARNING
if you pass poorly-converting scalar data to an internal function (For example, substr('foo', 'bar');) This changed my mind about the level of error to raise here. I think there's still a good argument for E_CATCHABLE_FATAL if you pass something retarded (like a resource, or possibly even an array), but I think we should strive as far as possible to be consistent with the behavior of scalars passed to internal functions. This would allow us to repaint the entire proposal as bringing to the language level the same level of scalar typing available internally, using the same syntax as the docs (which sounds much more reasonable and less politically charged than "Please add scalar typing...again".)
See Ferenc's reply about 30 seconds ago for more details on this...
Type hints are meant to
filter input from external sourcesCorrection, it should read like this:
Type hints are not meant to filter input from external sources
That's not really the point though. The issues with external sources providing strings comes into play regardless of whether people validated their inputs. For example, if (is_numeric($priority) && $priority >= 0 && $priority <= 3) will pass and still leaves you with a string, and that string currently works just fine everywhere as if it were an integer. What's more, the folks that will be voting on this have made it clear in the past that failure to account for type juggling in any such proposal is a deal breaker. For many users these inputs can and will trickle down through the code and eventually cause frustrating failures if not handled intelligently. You don't have to love it, but basically if you want a typing proposal to have any chance I think you'll have to support it.
John Crenshaw
Priacta, Inc.
2012/3/8 John Crenshaw johncrenshaw@priacta.com:
From: Arvids Godjuks [mailto:arvids.godjuks@gmail.com]
I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.I think "Catchable fatal error should" be fine and users are familiar with such mechanic because it already exists. Consistency, man, consistency :)
Yeah, I was a huge advocate of this too until recently. I've changed my mind though, ironically enough to ensure better consistency.
PHP since 5.3 gives an
E_WARNING
if you pass poorly-converting scalar data to an internal function (For example, substr('foo', 'bar');) This changed my mind about the level of error to raise here. I think there's still a good argument for E_CATCHABLE_FATAL if you pass something retarded (like a resource, or possibly even an array), but I think we should strive as far as possible to be consistent with the behavior of scalars passed to internal functions. This would allow us to repaint the entire proposal as bringing to the language level the same level of scalar typing available internally, using the same syntax as the docs (which sounds much more reasonable and less politically charged than "Please add scalar typing...again".)See Ferenc's reply about 30 seconds ago for more details on this...
Well, it may be that way too, but I have to point out that language
level functions are built in and you can't add or remove a type hint
for them. It expects integer and does it's best to make it an integer,
even if it gives some weird result. And backwards compability is an
issue here - the main issue. At the language level you have to
maintain that BC and sure if you make zend_parse_params reject strings
where an in should be without any warning - you sure have a rage storm
on the internet that will crush you to peaces.
Adding optional type hinting isn't bound to that BC, because we have
no scalar type hints at all. In 5.3 they added E_NOTICE
and E_WARNING
to zend_parse_params. Are you sure they would not change the E_WARNING
to E_ERROR
in say PHP 6? Or bump E_NOTICE
to E_WARNING? What if
type-juggling rules change? If that will happen - you will have your
type hint behavior change between versions and I think that's not
really a good idea.
So from one point of view it's a nice idea to tie that to
zend_param_parse, but from the other side that does not look like a
good idea. Internals of the engine tend to change more often than the
external syntax and behavior.
Type hints are meant to
filter input from external sourcesCorrection, it should read like this:
Type hints are not meant to filter input from external sourcesThat's not really the point though. The issues with external sources providing strings comes into play regardless of whether people validated their inputs. For example, if (is_numeric($priority) && $priority >= 0 && $priority <= 3) will pass and still leaves you with a string, and that string currently works just fine everywhere as if it were an integer. What's more, the folks that will be voting on this have made it clear in the past that failure to account for type juggling in any such proposal is a deal breaker. For many users these inputs can and will trickle down through the code and eventually cause frustrating failures if not handled intelligently. You don't have to love it, but basically if you want a typing proposal to have any chance I think you'll have to support it.
John Crenshaw
Priacta, Inc.
That's why I described the rules when type juggling comes into play.
If you send a string number, it is converted from string to number by
the type hint. If you send a string of characters and pass it to a int
type hinted function - sorry, but it's you who shout yourself with a
shotgun, not someone else.
I have to repeat it again - type hinting is not for converting and
filtering data. It is not meant to be used in code witch deals with
user input.
You will never write a code like this in 5.3 or 5.4
<?php
function processArray(array $data) {
foreach ($data as $k => $v) {
// Do something
}
}
processArray($_POST['some_var']);
?>
Should I tell you why? I think you know. Same goes for hinting
integer, string, float, bool or any other type. To convert data we
have conversion operators and functions like settype. Hints only
should take into account that a validated param can be a number in
string representation and change the type accordingly. But if passed
something different than a number - fail.
From: Arvids Godjuks [mailto:arvids.godjuks@gmail.com]
That's why I described the rules when type juggling comes into play.
If you send a string number, it is converted from string to number by the type hint. If you send a string of characters and pass it to a int type hinted function - sorry, but it's you who shout yourself with a shotgun, not someone else.
If you are determined to have it this way and cannot yield, then you are off topic. This thread was built around the explicit premise that any scalar type hint MUST be more forgiving than that, and if we take that away there's quite literally nothing more to talk about. Regardless of how anyone feels about it, the core devs will never accept what you are insisting on above. (If you want proof, look at the prior debates on this issue.) This discussion has no purpose unless it can actually accomplish something meaningful, so it started by accepting this as a fundamental requirement. Allowing strings to be implicitly converted to lower types when possible, regardless of whether the reason offends your sense of how code should have been written, is a vital compromise in the process of improving the typing in PHP.
John Crenshaw
Priacta, Inc.
2012/3/8 John Crenshaw johncrenshaw@priacta.com:
From: Arvids Godjuks [mailto:arvids.godjuks@gmail.com]
That's why I described the rules when type juggling comes into play.
If you send a string number, it is converted from string to number by the type hint. If you send a string of characters and pass it to a int type hinted function - sorry, but it's you who shout yourself with a shotgun, not someone else.If you are determined to have it this way and cannot yield, then you are off topic. This thread was built around the explicit premise that any scalar type hint MUST be more forgiving than that, and if we take that away there's quite literally nothing more to talk about. Regardless of how anyone feels about it, the core devs will never accept what you are insisting on above. (If you want proof, look at the prior debates on this issue.) This discussion has no purpose unless it can actually accomplish something meaningful, so it started by accepting this as a fundamental requirement. Allowing strings to be implicitly converted to lower types when possible, regardless of whether the reason offends your sense of how code should have been written, is a vital compromise in the process of improving the typing in PHP.
John Crenshaw
Priacta, Inc.
Well, if your type hints gets more forgiving, than it's the same that
was proposed by this
function a((int) $arg) {}
And in this case hints have no meaning at all - it's just other syntax
to do the conversion that now looks like this
function a($arg) { $arg = (int)$arg; }
And please give an answer to this question: If we make hints forgiving
(like type casting), then what we have to do with current array type
hints - it gives error on anything but arrays? Change it back so it
does a conversion to array? Sorry, but it will make a mess in my code,
because I already use hints for arrays and objects and changing their
behavior is just out of the question.
I do not remember devs explicitly saying that something like I
proposed will not be accepted. They said there will be no strict type
hinting or strict variable typing. And they do not want to add another
syntax for type juggling functionality. So, if only i'm not mistaken,
my idea is somewhere in between and doesn't look weird or
extraordinary. It just adds ability to make arguments of the
function/method be more picky about what they can receive.
Maybe i'm mistaken, but I have a distinct impression that many of the
posters will use type hints all over the place if and when they will
be added and base their ideas on that. Don't get me wrong, but the
auto-casting type hints are really needed only when you really write
all the code with type hints in every function/method you define and
you don't want to do manual conversions all the time.
Maybe this is that case when people tend to get min-max and do not
consider the average use? My average use of currently available type
hints is low in WEB environment and only in internal stuff where user
input doesn't make in unchecked. And I had quite a good use of them in
a console daemon where there is no user input at all (only working
with database).
As to breaking some BC when making keywords such as "string", "int",
"float" - that's what the major releases are for. When you introduce
ANY keyword there is a possibility that someone is using it and it
will break his application. It's a risk, yes. But now days refactoring
instruments are very good and changing class name thought out the
project is no big deal really - just make sure people are informed.
Well, if your type hints gets more forgiving, than it's the same that was
proposed by this function a((int) $arg) {} And in this case hints have no
meaning at all - it's just other syntax to do the conversion that now looks
like this function a($arg) { $arg = (int)$arg; }
That's black and white thinking. Casting is obviously too forgiving (a cast literally accepts ANYTHING), and there were specific problems identified with that syntax that have absolutely nothing to do with whether you can juggle parameter types.
Current sentiment seems to be settling around behavior similar to the internal zend_parse_parameters, which is to say:
(function(int){})('1'); // no error
(function(int){})('123xyz'); // E_NOTICE, function gets (int)1
(function(int){})('xyz'); // E_WARNING, function gets (int)0
Someone (you?) made a good case for questioning these warning levels, but the basic concept of what to accept and what to warn about is good, and already in use (which makes it far easier to accept).
And please give an answer to this question: If we make hints forgiving (like
type casting), then what we have to do with current array type hints - it
gives error on anything but arrays? Change it back so it does a conversion
to array? Sorry, but it will make a mess in my code, because I already use
hints for arrays and objects and changing their behavior is just out of the
question.
Array behaves as it always has (E_RECOVERABLE_ERROR if you don't pass an array). Scalar types don't implicitly convert ("juggle") to arrays, so there's no issue there. There's no reason to attempt to support any implicit conversion from array to string either. E_RECOVERABLE_ERROR
would be perfectly appropriate here (or you could argue to raise E_WARNING, which is technically what zend_parse_parameters does).
I do not remember devs explicitly saying that something like I proposed will
not be accepted. They said there will be no strict type hinting or strict
variable typing. And they do not want to add another syntax for type juggling
functionality. So, if only i'm not mistaken, my idea is somewhere in between
and doesn't look weird or extraordinary. It just adds ability to make arguments
of the function/method be more picky about what they can receive.
Look back at the discussion and arguments. The string input thing comes up over and over again. Resisting this point simply caused frustration and ultimately turned into a consistent battle cry of "we're never going to add strict typing because it breaks the language and virally affects all the code up the chain". The input parameters became a poster child case, but conceptually if you make this too strict it virally forces everything up the stack to behave strictly as well (hence the frequent arguments, "it will break the language", and "it would no longer be PHP".)
You can disagree, that's totally fine, but this discussion assumes that a successful proposal must take the opposite route, and fully embrace string inputs and limited type juggling.
Maybe i'm mistaken, but I have a distinct impression that many of the posters
will use type hints all over the place if and when they will be added and base
their ideas on that. Don't get me wrong, but the auto-casting type hints are
really needed only when you really write all the code with type hints in every
function/method you define and you don't want to do manual conversions all the
time.
I'd use it liberally, especially in models, but not universally by a long shot. Type hints aren't designed to make life easier for the caller (though they should avoid making it harder). Type hints are connected to the algorithm of the function itself; they offer a logical guarantee to the function that the types of the parameters are consistent with the nature of the algorithm. For example, an add() function needs to be able to trust that parameters will be numeric, substr needs to be able to trust that parameters will be a string + an integral value, and so on.
If the logic requires this simple assurance, I'll use a hint. If not, I won't.
Maybe this is that case when people tend to get min-max and do not consider the
average use? My average use of currently available type hints is low in WEB
environment and only in internal stuff where user input doesn't make in unchecked.
And I had quite a good use of them in a console daemon where there is no user
input at all (only working with database).
The current hints consist only of arrays and classes. These can't be user inputs (well, arrays can, but really, that's so rare for someone to actually use.) Checked or unchecked is basically irrelevant, because these parameters could never have originated as user data anyway. Strings, integers, numbers, values used in boolean checks, these all can and will originate as user data, which is the concern raised over and over in the past. This is a fair argument. One can argue that people shouldn't have written their code that way, but they will, and do, and it "works". Continuing to behave reasonably in these cases has been important to the core devs in the past. Assurances that we'll support this case have been incredibly effective so far in calming frustrated people jumping into the middle of this discussion.
As to breaking some BC when making keywords such as "string", "int", "float" -
that's what the major releases are for. When you introduce ANY keyword there is a
possibility that someone is using it and it will break his application. It's a
risk, yes. But now days refactoring instruments are very good and changing class
name thought out the project is no big deal really - just make sure people are
informed.
I think we all mostly agree on this point. Reserving these and other keywords isn't going to be a major hangup.
John Crenshaw
Priacta, Inc.
On Thu, Mar 8, 2012 at 6:08 PM, John Crenshaw johncrenshaw@priacta.comwrote:
Well, if your type hints gets more forgiving, than it's the same that was
proposed by this function a((int) $arg) {} And in this case hints have no
meaning at all - it's just other syntax to do the conversion that now
looks
like this function a($arg) { $arg = (int)$arg; }That's black and white thinking. Casting is obviously too forgiving (a
cast literally accepts ANYTHING), and there were specific problems
identified with that syntax that have absolutely nothing to do with whether
you can juggle parameter types.Current sentiment seems to be settling around behavior similar to the
internal zend_parse_parameters, which is to say:
(function(int){})('1'); // no error
(function(int){})('123xyz'); // E_NOTICE, function gets (int)1
(function(int){})('xyz'); // E_WARNING, function gets (int)0
I don't think it's fair to say that casting is too forgiving OR that
current sentiment is settling around behavior similar to the internal
zend_parse_parameters. This is a complex issue, and there are many core
developers who have been focusing on other things besides this discussion.
Their silence likely does not demonstrate sentiment of approval for
anything at this point. This particular subject has much history on the PHP
mailing list, and the opinions are far ranging. More importantly, this
general subject has much history in all of the programming languages that
are dynamically typed.
One can find similar discussions regarding Ruby, Python, and general
discussions of type:
http://www.codecommit.com/blog/ruby/adding-type-checking-to-ruby
http://stackoverflow.com/questions/734368/type-checking-of-arguments-python
http://journal.stuffwithstuff.com/2010/08/31/type-checking-a-dynamic-language/
And, while there are some dynamically typed languages that allow optional
types, they don't provide much help here, either:
- Clojure allows type hints, but they're just for performance reasons.
http://clojure.org/java_interop - Dart has optional types, but in Dart, everything is an object AND it's
types are unsound (i.e., let you get away with lots):
http://www.dartlang.org/articles/why-dart-types/
My point is that there are many beliefs about how to handle optional type
checks on function arguments in dynamic, weakly typed languages, and
there's not much precedent. That's not to say that nothing should be added
to PHP's capabilities. However, one constant question that emerges when
considering types in dynamic languages is what does it really buy you? The
value has to be significant, especially considering the lack of a compiler
that can ensure the correctness of a type before runtime. As Stas pointed
out in the thread for the Enun RFC (noting the importance of a compiler):
One note here: Java is a statically typed compiled language. PHP is not. So
many arguments regarding type safety, etc. which are completely valid in
regards to Java have no validity in regard to PHP. I understand that some
people want to import some bits from strictly typed languages, imagining
that this will provide them with benefits that statically typed languages
have, namely compile-time safety checks, etc. This does not work as well in
dynamic languages. Note for example that neither Ruby nor Python have
enums, though you can do similar things there.
Let's look at the examples you gave:
(function(int){})('1'); // no error
(function(int){})('123xyz'); // E_NOTICE, function gets (int)1
(function(int){})('xyz'); // E_WARNING, function gets (int)0
I'm wondering where you would be getting the values '123xyz' and 'xyz' from
at runtime that you're passing off to a function expecting ints? If these
come from GPC's, then wouldn't an app pick up the issue BEFORE getting to
the point that they're being used as arguments through proper input
validation. And, if these come from a MySQL database, then wouldn't they
have been stored in a field that only stores some type of int (otherwise
one wouldn't be passing them to a function expecting ints.) And, if it
comes from a file, wouldn't the input be validated there, too, before
calling this function? Now, I'm not saying there are no examples, but they
would appear to be very limited in applications.
Joe Armstrong, creator of the dynamically typed Erlang language, advocates
performing checks on the datatypes at the points in the application that
receive input, but not within the internal functions. It's an interesting
view, and he seems to have had success building robust, stable software
using this approach. Now, I'm not saying that this should be PHP's
approach. I recently presented the idea of having a scalar type (with
aliases) because this could identify problems the first time a PHP file is
parsed rather than at runtime. However, I do bring up Joe Armstrong's
approach to temper the belief that casting or something less is "too
forgiving."
I am interested in adding some type of ability to PHP to catch issues at
parse time rather than runtime. And, I very much enjoyed seeing someone as
skilled as Anthony crank out a quick proof-of-concept (I'd still be sifting
through Zend's internals trying to get out of my Objective-C mode of
thinking.) I just hope that we look at all options (including doing
nothing), consider the research already done on dynamic type systems, and
look to examples in other programming languages that can give us insights
into what works well and what doesn't.
Adam
From: Adam Jon Richardson [mailto:adamjonr@gmail.com]
I don't think it's fair to say that casting is too forgiving OR
that current sentiment is settling around behavior similar to the
internal zend_parse_parameters. This is a complex issue, and there
are many core developers who have been focusing on other things
besides this discussion. Their silence likely does not demonstrate
sentiment of approval for anything at this point. This particular
subject has much history on the PHP mailing list, and the opinions
are far ranging. More importantly, this general subject has much
history in all of the programming languages that are dynamically
typed.
Sorry, you misunderstood. What I meant was not that core developers had bought into this (whether that will happen is unknown.) I meant that the discussion in this thread among the most active participants appeared to shift hard this direction as soon as it was proposed (can't remember who by.) Taken in the context of everything else it was a good foundation that solved a number of problems all at once.
Let's look at the examples you gave:
(function(int){})('1'); // no error, function gets (int)1
(function(int){})('123xyz'); // E_NOTICE, function gets (int)123
(function(int){})('xyz'); // E_WARNING, function gets (int)0I'm wondering where you would be getting the values '123xyz' and 'xyz' from at runtime...
It doesn't so much matter where it comes from or why. The spec has to define how such inputs are handled (the behavior can't be undefined). E_NOTICE
and E_WARNING
matches a behavior that we know has already been considered acceptable in the core (I.E. this is the behavior of substr()
).
Joe Armstrong, creator of the dynamically typed Erlang language,
advocates performing checks on the datatypes at the points in the
application that receive input, but not within the internal functions.
It's an interesting view, and he seems to have had success building
robust, stable software using this approach.
I tend to agree, but this sort of argument hasn't held much sway in the past on the typing issue in PHP so in terms of designing a viable RFC that can pass a vote I don't see that it matters much what we think here.
Now, I'm not saying that this should be PHP's approach. I recently
presented the idea of having a scalar type (with aliases) because
this could identify problems the first time a PHP file is parsed
rather than at runtime. However, I do bring up Joe Armstrong's
approach to temper the belief that casting or something less is
"too forgiving."
At least for me, script inputs are far less important than other stuff; for example, generating good errors after a refactoring mistake. Allowing everything to pass through without errors solves the documentation issue, but basically nothing else.
I very much enjoyed seeing someone as skilled as Anthony crank out
a quick proof-of-concept (I'd still be sifting through Zend's
internals trying to get out of my Objective-C mode of thinking.)
Yes, huge thanks for Anthony's contributions here.
I just hope that we look at all options (including doing nothing),
consider the research already done on dynamic type systems, and look
to examples in other programming languages that can give us insights
into what works well and what doesn't.Adam
Agreed. I've been advocating the collection and organization of information from prior discussions for a while. If there is good stuff to learn from discussions in similar languages we should look over that too. The primary barrier I see here is time. Looking over all this will take a lot of work.
John Crenshaw
Priacta, Inc.
On Thu, Mar 8, 2012 at 10:03 AM, Arvids Godjuks arvids.godjuks@gmail.comwrote:
Hi Simon!
2012/3/8 Simon Schick simonsimcity@googlemail.com:
Hi Arvids,
I pretty much like this idea as it's more strict. Let me say something
to the questions you pointed out here.2012/3/7 Arvids Godjuks arvids.godjuks@gmail.com:
I realize that with scalars it's not that straight forward, but
complicating things by adding an auto-cast syntax and so on is just
ridiculous. Hints should stay, well, hints. The only problem we have
is complications of accepting numerical strings or numbers as strings.
And what to do with "null".I'd like to handle it the same way as it's handled with the classes
right now. If null is not the default-value you'll get an error when
you pass null in there.
One thing I'd like opened here: If you define a default-value
different than null, should you be able to pass null as well and the
compiler will use the default-value?function a(bool $bool) {}
a(10); // Kill your self against the wall - write a(true);
If you define bool - use the damn bool!I like that. What should we do if this appears? As it's now - just
throw an "Catchable fatal error" and let the script blow-up? I would
go this far.I think "Catchable fatal error should" be fine and users are familiar
with such mechanic because it already exists. Consistency, man,
consistency :)I consider interchangeable only three cases:
- Numerical string.
- Integers and floats as strings.
- Integer and string 0 1 as bool.
Any other cases should error out.
Until now I thought about the weak variable-types as a order ...
string, float, integer, Boolean.
All Boolean values are compatible be an integer (0 or 1) and all
integer are compatible to a float and so on. Do you think it's good to
have it this way? This would mean that you could also get a Boolean
true as string "1" ... I personally don't like that ... but I don't
know where to draw the strict-line.
Now think about that backwards. Can a "1" be passed as a parameter
that expects Boolean? If yes, I'd keep it consistent in both ways.Bye
SimonThat's a good tricky question, I like it.
Well, I think the lower should work just fine.
function a(bool $int) {};
a("1");
AFAIR Gustavo, Anthony and Nikic discussed on IRC, that maybe the best
solution for scalar type hints would be the unification of the scalar type
hints with the current implementation of zend_parse_parameters.
the built in php functions are "enforcing" the function signature via
parsing the parameters through this call.
so for example the above mentioned substr signature is substr ( string
$string , int $start [, int $length ] )
substr("foobar", "123"); // works like a charm
substr("foobar", 1.5); // works, no warning/notice, although we lose
precision here,
substr("foobar", "123 asd"); // Notice: A non well formed numeric value
encountered
substr("foo", "bar"); // Warning: substr()
expects parameter 2 to be long,
string given
so if we would implement the scalar typehints in a way to map the signature
types to the zpp call, then that would mean that the scalar hints are
consistent across the built-in functions, the documentation, and the
dynamic nature of the language(as one could argue that the current/future
implementation of zend_parse_parameters is in line with the dynamic
casting/type juggling nature of php.
just my 2cents
--
Ferenc Kovács
@Tyr43l - http://tyrael.hu
AFAIR Gustavo, Anthony and Nikic discussed on IRC, that maybe the best
solution for scalar type hints would be the unification of the scalar type
hints with the current implementation of zend_parse_parameters.
Yeah, that's basically what we were discussing. However, there's one
significant issue that I personally have to doing that. in ZPP, if
you have a parameter that expects an array, and pass it an int, a
warning is raised. But then the main body of the function is skipped
(the function isn't executed) and the control is passed back to the
calling code.
To me, that's not right at all. That basically forces all code to use
boolean return error checking. Even if you wanted to use exceptions,
you'd still need to wrap the calling code in an if() statement to see
if a parameter errored. To me, that makes a direct port of zpp a
no-go for userland code. Sure, it would be consistent, but it would
also lead to some very hard-to-read code if you wanted to make it
robust:
try {
if (!foo($bar)) {
return false;
}
} catch (FooException $e) {
// We want to ignore it, because we're maintaining the abstraction
and can fix it
bar();
return false;
}
return true;
All that code, just to make a robust function call. Not good in my book.
the built in php functions are "enforcing" the function signature via
parsing the parameters through this call.
so for example the above mentioned substr signature is substr ( string
$string , int $start [, int $length ] )
substr("foobar", "123"); // works like a charm
substr("foobar", 1.5); // works, no warning/notice, although we lose
precision here,
substr("foobar", "123 asd"); // Notice: A non well formed numeric value
encountered
substr("foo", "bar"); // Warning:substr()
expects parameter 2 to be long,
string givenso if we would implement the scalar typehints in a way to map the signature
types to the zpp call, then that would mean that the scalar hints are
consistent across the built-in functions, the documentation, and the
dynamic nature of the language(as one could argue that the current/future
implementation of zend_parse_parameters is in line with the dynamic
casting/type juggling nature of php.
What I do like, is the rules for error or no error. How it determines
if a zval can be passed to a hint of integer. And I also like that it
casts if those rules pass...
However, I think the errors that it throws are far too kind, and can
be quite confusing and lead to difficult to defend code (meaning that
you need 10 or 15 lines of code to defensively call a piece of code).
Instead, I'd much prefer the error level be raised to
E_RECOVERABLE_ERROR, or throw an exception on those typing errors. At
least in user type hints, and preferably in ZPP as well. If the
function is not going to be executed, it should raise a much more
substantial error... Otherwise that is going to be more confusing
than anything else IMHO...
just my 2cents
Thanks for the reply!
Anthony
On Thu, 08 Mar 2012 13:38:32 +0100, Anthony Ferrara ircmaxell@gmail.com
wrote:
AFAIR Gustavo, Anthony and Nikic discussed on IRC, that maybe the best
solution for scalar type hints would be the unification of the scalar
type
hints with the current implementation of zend_parse_parameters.Yeah, that's basically what we were discussing. However, there's one
significant issue that I personally have to doing that. in ZPP, if
you have a parameter that expects an array, and pass it an int, a
warning is raised. But then the main body of the function is skipped
(the function isn't executed) and the control is passed back to the
calling code.
Not really, that's just a convention that if zpp fails functions return
null or false immediately (which one is used depends on the extension,
current weather, etc.). That's because there's a convention that builtin
functions don't raise exceptions. But nothings stops them from falling
back or suppressing the warning/notice (and some do, esp. if they support
distinct sets of arguments).
Some extensions (and constructors even in extensions that use false for
error) actually force an exception if zpp fails (usually via
zend_replace_error_handling).
But of course this is not an option in user code because:
- you can't change the error handling before parsing the parameters and
- inside the function you can't tell whether some argument parsing error
occurred.
So E_RECOVERABLE_ERROR
in the cases where zpp would return FAILURE seems
in fact the only viable option, even with the disadvantages it has
(centralization and lack of flexibility).
Still, the fact that 100% consistency is not possible is not a strong
argument against at least some consistency and in favor of inventing new
rules.
[...]
--
Gustavo Lopes
Gustavo,
Not really, that's just a convention that if zpp fails functions return null
or false immediately (which one is used depends on the extension, current
weather, etc.). That's because there's a convention that builtin functions
don't raise exceptions. But nothings stops them from falling back or
suppressing the warning/notice (and some do, esp. if they support distinct
sets of arguments).Some extensions (and constructors even in extensions that use false for
error) actually force an exception if zpp fails (usually via
zend_replace_error_handling).
Quite fair...
But of course this is not an option in user code because:
- you can't change the error handling before parsing the parameters and
- inside the function you can't tell whether some argument parsing error
occurred.
Which is the point.
So
E_RECOVERABLE_ERROR
in the cases where zpp would return FAILURE seems in
fact the only viable option, even with the disadvantages it has
(centralization and lack of flexibility).
So, at that point, then it sounds like we have a spec. Functionality
of zpp, with an E_RECOVERABLE_ERROR
where zpp would fail. Including
any warnings or notices that zpp would have raised anyway (since
`"1abc" would work when passed to an int, it should still work, notice
intact).
Still, the fact that 100% consistency is not possible is not a strong
argument against at least some consistency and in favor of inventing new
rules.
Sure. Makes sense.
I'll work on a proof-of-concept this weekend. That is if nobody else
wants to take it (or beats me to it) :-D.
Thanks,
Anthony
Stas,
Thanks for the comments!
inline.
Hi!
Just took a look on it - the syntax proposed there is quite ugly and rather
confusing, I really wouldn't like to have such syntax in PHP.
Ok, this is where I'm torn. I have a few (read: about 4 or 5)
responses (mostly from people I respect quite a bit) that say it's
quite ugly and confusing. I have had a lot more responses saying it's
simple, elegant and syntatically draws the difference between casting
and strict type checking. I see your point, I really do. It's not
the prettiest syntax out there. But confusing? I'm not so sure... I
think you're too close to the problem to really understand it. Or
perhaps I am... I don't know.
But based on the conversations I've had with all sorts of devs about
this (some that I don't know personally, some that I do, some junior,
some senior), the vast majority of them got it without explanation.
The fact that cast syntax was re-used gave them enough of a hint as to
what it was doing that they guessed correctly. Now, if you think it
should be doing something different, then definitely re-visit the
syntax. But if it's going to be casting variables, the syntax does
make sense and carries an intrinsic value with it...
Also "(int) $foo = “1” will generate an E_COMPILE_ERROR" makes no sense to
me.
Actually, that makes perfect sense to me. Think about it from the
reader perspective. Sure, "(int) $foo = '1'" is pretty straight
forward, but what you you think if you saw:
foo ((string) $bar = 123);
Frankly, that would confuse the daylights out of me, and would force
me to stop and think about what would happen. That's exactly what I
would like to avoid, the thinking step on reading it. In fact, it
would make even less sense, since it would need to be cast, so the
following would return false:
function foo((string) $bar = 123) {
return $bar === 123;
}
foo();
How much more confusing is that? By restricting the default parameter
to be of the type being casted to, that sort of a problem wouldn't
happen and would be adverted by the compiler...
I think the difference is that I know that strings are not integers
and vise versa. Even at the language level there are subtle
differences in behavior between the types, even if they store
equivalent values.
Also, this line:
function test((int) $intParam, (string) $strParam = "foo", (array) $array)
{}is not proper PHP code - it contains optional parameter and then parameter
with no default.
It is proper PHP code. It parses just fine
(http://codepad.viper-7.com/rEHqZp). Sure, it's not best practice
(and was an accident which has been fixed), but it's 100% valid and
proper PHP code and doesn't even raise E_STRICT
errors...
And can we please stop using word "hinting"?
We can call it type conversion, typecasting, type coercion, etc.
http://en.wikipedia.org/wiki/Type_conversion
Well, but I think that a distinction needs to be made about where it
is. How about "Parameter Casting". Better?
But I don't see how there's any hinting involved.
The compiler (and any IDE) knows what the type of the variable will be
inside the function body. How is that not hinting?
Anthony
Hi!
would make even less sense, since it would need to be cast, so the
following would return false:function foo((string) $bar = 123) {
return $bar === 123;
}
foo();
You explicitly said "convert, then compare excluding conversion", what
would you expect? That's like saying "why $a+1 is not equal to $a, it's
almost the same?". No it's not - you just told PHP to modify it!
How much more confusing is that? By restricting the default parameter
to be of the type being casted to, that sort of a problem wouldn't
happen and would be adverted by the compiler...
I feel you're painting yourself into a corner here - inventing arbitrary
restrictions and then inventing arbitrary problems to justify these
restrictions. Why would your conversion convert, but not always convert?
Why it would work with constants, but not in defaults?
It is proper PHP code. It parses just fine
(http://codepad.viper-7.com/rEHqZp). Sure, it's not best practice
The fact it parses doesn't mean it is proper code. The fact it's not
errors out is actually a bug, as such function definition is broken. But
let's not take the discussion too far out - just please do not promote
such code in our RFCs.
The compiler (and any IDE) knows what the type of the variable will be
inside the function body. How is that not hinting?
Hinting means something that is just for information and can be ignored
it you don't need it. This is type coercion - you can not ignore it, it
would change your variables. Calling it hinting implies it does not do
anything, just informs IDE - that'd what PHPDoc does, but that's not
what your proposed function does. Proper naming is important.
The compiler BTW doesn't know anything and has no way to know it and
benefit from it in any way.
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi,
It got quite around that because we have some RFCs to this where the functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to update the RFC - but as there's no one doing that, I think we're quite close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_typesBye
Simon
Sorry, I disagree. This is nowhere close IMO, and silence doesn't denote consent in this case. I actually basically stopped participating when it became apparent that people were determined to rush head first into creating a doomed RFC without any process to ensure that historical arguments were considered and addressed, with minimal attention to feedback, and with no concern for syntax (proposed syntax is as bad as the namespace syntax).
I'm in favor of addressing the type hinting issue, but I'm opposed to this RFC. It is crippled, confusing, and has a plethora of unaddressed issues. The object cast has similar problems, and although I recognize the value of this sort of functionality, the current proposal seems to mostly ignore a number of critical problems that were raised when it was discussed on the mailing list.
John Crenshaw
Priacta, Inc.
John,
Sorry, I disagree. This is nowhere close IMO, and silence doesn't denote consent in this case. I actually basically stopped participating when it became apparent that people were determined to rush head first into creating a doomed RFC without any process to ensure that historical arguments were considered and addressed, with minimal attention to feedback, and with no concern for syntax (proposed syntax is as bad as the namespace syntax).
Well, my take on it was that thinking out-loud in a thread is not
going to get us anywhere with nothing to base the conversation on. So
I picked an option and proposed it. As now, we can base the
conversation around a real implementation. Don't like the syntax?
Great! Let's find a better solution. But I felt that it was more
important to put a base for the conversation, rather than just letting
it wander aimlessly.
I'm in favor of addressing the type hinting issue, but I'm opposed to this RFC. It is crippled, confusing, and has a plethora of unaddressed issues.
Then point out the issues. Help improve it and make it something that
should go in the core. That's why it's still in draft mode. I
didn't propose it, or put it for discussion, I put it in draft for
that very reason.
As far as it being crippled, I'm not sure what you mean, just because
it's only doing casting?
As far as confusing, it is? I thought this was actually one of the
more straight forward proposals, since it re-used so much from the
core (meaning that it doesn't add new behavior, it re-uses existing
behavior).
As far as having a plethora of unadressed issues, I'm absolutely sure
it does. But I haven't seen a single one put out there so that it can
be fixed...
The object cast has similar problems, and although I recognize the value of this sort of functionality, the current proposal seems to mostly ignore a number of critical problems that were raised when it was discussed on the mailing list.
Which were? The critical problems that I saw on the list were mostly
related to the original proposal wrapping set() with __assign() (which
this proposal removed). The only known issues that I know of that
remains is with the __toScalar() part (which in worst case can be
removed from the proposal).
These are RFCs. I am (as their author) explicitly asking for your
comments and contribution. They are not set in stone in the least...
In fact, the only way they would get to the point where I would
propose them is with enough input and overview that it was mature.
They are not mature now.
Can we make them mature?
Thanks,
Anthony
Disclaimer: The following is direct (maybe brutally so). I'm not trying to hurt any feeling or attack, but I'm not pulling punches either. I don't have the energy right now to polish this and make it all nice and gentle, so I'm sorry in advance. I hope you'll look past the directness and be able to get some useful feedback.
John,
Sorry, I disagree. This is nowhere close IMO, and silence doesn't denote consent in this case. I actually basically stopped participating when it became apparent that people were determined to rush head first into creating a doomed RFC without any process to ensure that historical arguments were considered and addressed, with minimal attention to feedback, and with no concern for syntax (proposed syntax is as bad as the namespace syntax).
Well, my take on it was that thinking out-loud in a thread is not going to get us anywhere with nothing to base the conversation on. So I picked an option and proposed it. As now, we can base the conversation around a real implementation. Don't like the syntax?
Great! Let's find a better solution. But I felt that it was more important to put a base for the conversation, rather than just letting it wander aimlessly.
Yes, it was aimless discussion (though some would call it brainstorming). It was ready to move to the next level, which should have been gathering the constraints/requirements/problems into a coherent list to work from. What happened though was that this step was skipped entirely, so now there's been an attempt to write a preliminary spec without gathering the requirements first, which IMO is far worse than any amount of aimless discussion.
I'm in favor of addressing the type hinting issue, but I'm opposed to this RFC. It is crippled, confusing, and has a plethora of unaddressed issues.
Then point out the issues. Help improve it and make it something that
should go in the core. That's why it's still in draft mode. I didn't propose it, or put it for discussion, I put it in draft for that very reason.
A good number of issues with the current proposal were raised during the discussion on the mailing list. I don't feel like digging them all up right now, but off the top of my head I remember the following being raised and never saw any consensus for how to resolve them:
- inconsistent syntax (one syntax for scalars, a different one for classes)
- conflicting syntax (I.E. array vs. (array), RFC simply "allows" this, and ignores the confusion that this will create for users.)
- different from the syntax used in the docs
- lack of sufficient function to justify a core change
- chaos surrounding null (to accept and if so to cast or not? Creates a conflict between consistency and implications of the syntax)
- conflicts with references (RFC tries to address this by simply disallowing references, which IMO just ignores the need that would have caused this sort of code in the first place.)
There were others, but I'm not making an exhaustive list.
As far as it being crippled, I'm not sure what you mean, just because it's only doing casting?
Yes, casting is barely better than doing nothing. If I want a dumb typecast I can do that already. What I can't do without massive boilerplate everywhere is an intelligent conversion that accepts safe conversions and gives a warning or error on unsafe conversions.
As far as confusing, it is? I thought this was actually one of the more straight forward proposals, since it re-used so much from the core (meaning that it doesn't add new behavior, it re-uses existing behavior).
Yes, the syntax has some critical issues that create conflicting expectations. Look at the prior discussion. The current proposal doesn't really fix most of this.
As far as having a plethora of unadressed issues, I'm absolutely sure it does. But I haven't seen a single one put out there so that it can be fixed...
Again, look at the prior discussion of this syntax. Plenty of issues raised.
The object cast has similar problems, and although I recognize the value of this sort of functionality, the current proposal seems to mostly ignore a number of critical problems that were raised when it was discussed on the mailing list.
Which were? The critical problems that I saw on the list were mostly related to the original proposal wrapping set() with __assign() (which this proposal removed). The only known issues that I know of that remains is with the __toScalar() part (which in worst case can be removed from the proposal).
The biggest one that comes to mind is behavior with respect to operators. __toScalar() in your spec is an attempt to handle this, but IMO it really doesn't cut it. Off the top of my head problems with this solution include:
- This will lead to duplicated code
- Thinking about my own code, I have almost no idea how I would actually write a robust __toScalar() implementation. It's still going to be returning a string, or an integer. Very confusing.
These are RFCs. I am (as their author) explicitly asking for your comments and contribution. They are not set in stone in the least...
In fact, the only way they would get to the point where I would propose them is with enough input and overview that it was mature.
They are not mature now.Can we make them mature?
Thanks,
Anthony
Well, the big issue for me is that I think the type casting hints starts from a fundamentally bad foundation. The premise here is based on a syntax that is ugly and strange, and the syntax opens a bunch of new problems that I don't see a way to resolve. The reason for selecting this syntax was to avoid a BC break from reserving some new keywords. I don't really see this as a good trade.
As for the automatic casting functions, I like the concept, but some serious problems were raised in the discussions and many were never resolved very well. To some extent I'm not really seeing good solutions either. If I think of a solution I'll be sure to mention it, but right now this looks very much like a dead end to me.
John Crenshaw
Priacta, Inc.
John,
Disclaimer: The following is direct (maybe brutally so). I'm not trying to hurt any feeling or attack, but I'm not pulling punches either. I don't have the energy right now to polish this and make it all nice and gentle, so I'm sorry in advance. I hope you'll look past the directness and be able to get some useful feedback.
Thank you for being candid. I appreciate straight to the point
replies, as long as they are respectful (which yours was very much
so). So thank you. Now, to your points.
Yes, it was aimless discussion (though some would call it brainstorming). It was ready to move to the next level, which should have been gathering the constraints/requirements/problems into a coherent list to work from. What happened though was that this step was skipped entirely, so now there's been an attempt to write a preliminary spec without gathering the requirements first, which IMO is far worse than any amount of aimless discussion.
With all honesty, I didn't see anything being gathered. What I saw
was random ideas shot back and forth (with a good bunch ignored in all
the chatter). There didn't really seem to be one or two clear
directions, but instead at least a dozen directions at the same time.
There was talk about implementing a "scalar" hint, about implementing
strict hints again, about implementing pseudo-casting hints that did
only simple checks, about hints that actually casted, about hints that
threw notices, about hints that threw warnings.
There didn't seem to be anything more than a bunch of people wanting
different things not even paying attention to the other conversation.
Could a spec have been developed from that? Sure. Would it have?
I'm not so sure.
So I picked a direction that seemed consistent with as much of it as
possible, and went with it. I didn't ask anyone to stop other work,
or stop their discussion. I just saw an opportunity to unify the
conversation around what seemed to be a commonality between the
comversation, and I took it. If I stepped on anyone's toes, I'm
sorry...
A good number of issues with the current proposal were raised during the discussion on the mailing list. I don't feel like digging them all up right now, but off the top of my head I remember the following being raised and never saw any consensus for how to resolve them:
I went over the replies to the initial POC thread that I posted
(http://marc.info/?t=133066037200001&r=1&w=2) and I'll rebut your
replies.
- inconsistent syntax (one syntax for scalars, a different one for classes)
This is actually discussed in the RFC, as it is not inconsistent (it's
actually consistent with what the patch tries to achieve). The syntax
for classes and normal arrays is a strict check, where if the match
fails an error is thrown. This syntax attempts to distinguish between
that functionality by providing a different syntax altogether. And
since it's casting the parameters, the syntax feels natural (for that
goal).
- conflicting syntax (I.E. array vs. (array), RFC simply "allows" this, and ignores the confusion that this will create for users.)
Actually, it doesn't simply allow that. It did it for a very specific
reason. "array" is a strict check, and "(array)" is a casting check.
One will fatal if a non-array is passed, and the other will attempt to
convert the parameter to an array. Very different functionality,
which are both internally consistent with the other syntax...
- different from the syntax used in the docs
Actually, it's the exact same syntax used for casting in the docs.
It's different from class type hints, because it's intended to be so.
If you don't like it, that's fine. But it's intentionally different.
- lack of sufficient function to justify a core change
That's absolutely something to be considered. However, I see erroring
on invalid casts as a bigger issue not the responsibility of a
casting hint patch. So that's why I mention explicitly in the RFC
and my blog post that solving that problem should be another RFC
(culminating in a series of 3 RFCs that each work together very well
to fill the overall need).
- chaos surrounding null (to accept and if so to cast or not? Creates a conflict between consistency and implications of the syntax)
That's absolutely a valid concern. And that's what should be being
discussed, if people really feel that the current implementation is
wrong...
- conflicts with references (RFC tries to address this by simply disallowing references, which IMO just ignores the need that would have caused this sort of code in the first place.)
Actually, it explicitly disallows references. This was added because
it was explicitly requested on the list in many discussions (including
the initial one for the POC). But if you can make a case on why to
implement it, and why it makes sense, then we can add it back.
There were others, but I'm not making an exhaustive list.
Well, the ones that I saw were either rectified, requested (and
implemented) or (to me) showed a lack of understanding about the
rationale and decisions (which is valid, but shouldn't really bear
that much on the discussion, as I feel if you want to raise an issue,
you should at least have a cursory understanding of what you're
commenting about)...
As far as it being crippled, I'm not sure what you mean, just because it's only doing casting?
Yes, casting is barely better than doing nothing. If I want a dumb typecast I can do that already. What I can't do without massive boilerplate everywhere is an intelligent conversion that accepts safe conversions and gives a warning or error on unsafe conversions.
Again, I personally see casting data-loss a bigger issue than just
parameter hinting, which should get its own RFC to clean up. That's
why I didn't include it here. On purpose...
As far as confusing, it is? I thought this was actually one of the more straight forward proposals, since it re-used so much from the core (meaning that it doesn't add new behavior, it re-uses existing behavior).
Yes, the syntax has some critical issues that create conflicting expectations. Look at the prior discussion. The current proposal doesn't really fix most of this.
Conflicting expectations? It looks like a cast to me, and that's what
it does. I'm not sure where the conflicting expectation is. I would
agree if it was foo(int $int) that did the casting. That would be
conflicting. But with the current syntax, I'm not sure I understand
your point...
As far as having a plethora of unadressed issues, I'm absolutely sure it does. But I haven't seen a single one put out there so that it can be fixed...
Again, look at the prior discussion of this syntax. Plenty of issues raised.
Actually, I did. And the only issue raised was by you here:
(http://marc.info/?l=php-internals&m=133066473032680&w=2). And I
believe those issues were addressed in the RFC. If you don't feel
that's adequate, that's fine, let's improve the RFC so that it does...
The biggest one that comes to mind is behavior with respect to operators. __toScalar() in your spec is an attempt to handle this, but IMO it really doesn't cut it. Off the top of my head problems with this solution include:
- This will lead to duplicated code
It will? Yes, __toInt() and __toScalar() may have the same code in
it. But that's always going to happen, unless you want to make "+" an
integer operation. But you could just do __toScalar() { return (int)
$this; } to take care of that duplication. The key is that it leaves
the determination of the type to return to the class, where it
belongs...
- Thinking about my own code, I have almost no idea how I would actually write a robust __toScalar() implementation. It's still going to be returning a string, or an integer. Very confusing.
You probably won't implement it at all then. I admit, the
__toScalar() method is the weak point of the RFC. I personally want
the flexibility that it provides, but if people are strongly against
it, I think it can be removed without destroying the RFC's intent...
Well, the big issue for me is that I think the type casting hints starts from a fundamentally bad foundation. The premise here is based on a syntax that is ugly and strange, and the syntax opens a bunch of new problems that I don't see a way to resolve. The reason for selecting this syntax was to avoid a BC break from reserving some new keywords. I don't really see this as a good trade.
To be perfectly clear, the reason for that syntax was not to avoid
a BC break. It was to avoid a FC break. I wanted a casting hint, and
I didn't want to restrict the possibility of adding strict hints
later. And I wanted to clearly distinguish the current strict hints
(array + class) and the new casting hints. To me, the most logical
way of doing that was to re-use the casting syntax. Could we have
done foo(int? $foo) or foo(*int $foo) or foo(@int $foo) or whatever?
Sure. But I'd argue that anything except foo(int $foo) would have
lead to FAR more confusion.
This way, it's re-using an existing syntax that every intermediate
developer is intimate with, and applying it to a case that's basically
functioning along the same lines...
As for the automatic casting functions, I like the concept, but some serious problems were raised in the discussions and many were never resolved very well. To some extent I'm not really seeing good solutions either. If I think of a solution I'll be sure to mention it, but right now this looks very much like a dead end to me.
Actually, there weren't. This is the thread you were referring to:
(http://marc.info/?t=133026833200004&r=1&w=2). And re-reading it, the
problems that are raised are all centered around __assign() (and ever
so slightly the scalar casting now implemented as __toScalar()). The
rest of it was barely discussed, and no real problems were raised.
I'm not saying this to say that there are no problems. I'm saying
that, as far as I've seen, no significant (non-personal-preference)
issues have been raised about the topics both of these RFCs discuss
(with the possible exception of __toScalar(), to a far lesser extent).
The topics that were objected two in those threads have been
rectified or eliminated altogether from these RFCs.
So, again, I ask. Let's look at the actual issues, so we can make
these RFCs better (or show that they need to be thrown out). I want
the best overall outcome, and if that means ditching my concepts
altogether, I have no problem with that. I just don't want to see
them ditched because of invalid pre-conceived notions, or because of
miss-communication.
Thanks for the replies!
Anthony
From: Anthony Ferrara [mailto:ircmaxell@gmail.com]
John,
A good number of issues with the current proposal were raised during the discussion on the mailing list. I don't feel like digging them all up right now, but off the top of my head I remember the following being raised and never saw any consensus for how to resolve them:
I went over the replies to the initial POC thread that I posted
(http://marc.info/?t=133066037200001&r=1&w=2) and I'll rebut your replies.
You've been spending a lot of time defending these proposals and trying to prove wrong feedback that raises concerns. This is preventing you from actually using the feedback to improve the proposals. You are losing out on perhaps the biggest advantage of the RFC process, which is that multiple minds can work together to hammer out an idea and make it really shine.
Most of your "rebuttals" focus entirely on whether the RFC contains sufficient information to make something technically work. That's not the point at all. I've read the RFC. I have no doubt that it "works", nor I think does anyone else. That's not the issue.
To quote a recent film: "Titan: Oh yeah? What's the difference? Megamind: PRESENTATION!". The code syntax is the UI that PHP presents to developers. Yes, this "works" (in the sense that it is possible to implement what the RFC describes), but there are serious usability and communication problems. Language is also one of the trickiest interfaces to work with because once you commit to something you are pretty much stuck with it forever (namespace separator). If every PHP developer is going to have to deal with this until the end of time it needs to be awesome.
- inconsistent syntax (one syntax for scalars, a different one for
classes)This is actually discussed in the RFC, as it is not inconsistent (it's actually consistent with what the patch tries to achieve). The syntax for classes and normal arrays is a strict check, where if the match fails an error is thrown. This syntax attempts to distinguish between that functionality by providing a different syntax altogether. And since it's casting the parameters, the syntax feels natural (for that goal).
You can mince words, but that doesn't change the problem. It is utterly inconsistent with the expectations in creates. You'll argue that it creates an expectation of a type cast, but you'd be wrong in far too many cases. The syntax is similar enough to the syntax for parameter types in other languages that developers will think of it as basically the same thing. The syntax differs however from existing parameter type syntax.
The behavioral difference is also a problem, being too different from parameter typing to be useful (it doesn't actually vet the parameter), and yet close enough to validate the confusion (behaves too similarly to an implicit conversion). In the end you have a bizarre syntax that looks like one thing but is conceptually another, but with a subtle behavioral difference that is invisible except when it fails to fail.
- conflicting syntax (I.E. array vs. (array), RFC simply "allows"
this, and ignores the confusion that this will create for users.)Actually, it doesn't simply allow that. It did it for a very specific reason. "array" is a strict check, and "(array)" is a casting check.
One will fatal if a non-array is passed, and the other will attempt to convert the parameter to an array. Very different functionality, which are both internally consistent with the other syntax...
I know about the behavioral difference. I'm not talking about a technical conflict, I'm talking about a conflict in the mind of the developer. Given function(array $a, (array) $b){} the difference between $a and $b is a very advanced distinction and will be completely lost by the average developer.
The confusion is made worse by the fact that function(array $a) works, but function(int $a) doesn't, but function((int) $a) does. I know why, but the average developer just learning PHP for the first time won't get it at all.
- different from the syntax used in the docs
Actually, it's the exact same syntax used for casting in the docs.
It's different from class type hints, because it's intended to be so.
If you don't like it, that's fine. But it's intentionally different.
Sometimes I think you miss the point on purpose.
In the docs substr is defined as:
string substr ( string $string , int $start [, int $length ] )
If I wanted to write the same thing in my own code I would have to write:
function my_substr ( (string) $string , (int) $start , (int) $length )
One syntax for the docs, a different one in my code.
- lack of sufficient function to justify a core change
That's absolutely something to be considered. However, I see erroring on invalid casts as a bigger issue not the responsibility of a
casting hint patch. So that's why I mention explicitly in the RFC and my blog post that solving that problem should be another RFC (culminating in a series of 3 RFCs that each work together very well to fill the overall need).
Well, if you argue that this proposal is actually a typecasting enhancement and not a parameter type enhancement, then yes, you'd be right. That's not how this is presented though, that's not where it is presented (Scalar Type Hinting discussion), that's not when it was presented, and that's not how it is getting perceived or measured.
As far as expanding type casting in this way, it doesn't make sense. There is no precedent, it looks and will get treated like parameter hinting (which you are saying it isn't), there is no additional functional value, and very little value of any sort beyond casts (just a tiny documentation boost and a savings in the number of characters in the few cases where a dumb type cast is good enough.)
- chaos surrounding null (to accept and if so to cast or not? Creates
a conflict between consistency and implications of the syntax)That's absolutely a valid concern. And that's what should be being discussed, if people really feel that the current implementation is wrong...
- conflicts with references (RFC tries to address this by simply
disallowing references, which IMO just ignores the need that would
have caused this sort of code in the first place.)Actually, it explicitly disallows references. This was added because it was explicitly requested on the list in many discussions (including the initial one for the POC). But if you can make a case on why to implement it, and why it makes sense, then we can add it back.
Again, yes, I know that the RFC takes a position on this. My point is not that the RFC doesn't take a position, my point was that the position taken "ignores the need that would have caused this sort of code in the first place."
Reference parameters are basically return values. Just because a parameter will return a value doesn't mean that the type no longer matters. In fact, it means that the calling function should EXPECT the type to change, and EXPECT the value to be modified. One example that occurs to me off hand is preg_match, where the 3rd parameter is documented as an array reference. You can actually pass anything, but it's going to be an array when the function returns.
There were others, but I'm not making an exhaustive list.
Well, the ones that I saw were either rectified, requested (and
implemented) or (to me) showed a lack of understanding about the rationale and decisions (which is valid, but shouldn't really bear that much on the discussion, as I feel if you want to raise an issue, you should at least have a cursory understanding of what you're commenting about)...As far as it being crippled, I'm not sure what you mean, just because it's only doing casting?
Yes, casting is barely better than doing nothing. If I want a dumb typecast I can do that already. What I can't do without massive boilerplate everywhere is an intelligent conversion that accepts safe conversions and gives a warning or error on unsafe conversions.
Again, I personally see casting data-loss a bigger issue than just parameter hinting, which should get its own RFC to clean up. That's why I didn't include it here. On purpose...
You can't raise errors like this on lossy casts. Giving a warning if an implicit conversion loses data (123 + '456xyz', or substr('foo', 'bar')) makes sense, but if I explicitly write (int)'456xyz' or (int)23.7, I must not get a warning about data loss (otherwise it would be difficult/impossible to force a deliberately lossy conversion without warnings). Since we can't raise warnings on casts, you really won't be able to do it with casted parameters either (unless you're willing to accept a consistency break). These will be stuck in silence forever.
Well, the big issue for me is that I think the type casting hints starts from a fundamentally bad foundation. The premise here is based on a syntax that is ugly and strange, and the syntax opens a bunch of new problems that I don't see a way to resolve. The reason for selecting this syntax was to avoid a BC break from reserving some new keywords. I don't really see this as a good trade.
To be perfectly clear, the reason for that syntax was not to avoid a BC break. It was to avoid a FC break. I wanted a casting hint, and I didn't want to restrict the possibility of adding strict hints later. And I wanted to clearly distinguish the current strict hints (array + class) and the new casting hints. To me, the most logical way of doing that was to re-use the casting syntax. Could we have done foo(int? $foo) or foo(*int $foo) or foo(@int $foo) or whatever?
Well, if that is the case, you did not succeed. The FC break you originally worked to avoid is something that can never happen anyway, and this does not avoid the most critical FC break.
First, "strict" types (in the sense of not allowing an integer to be passed to a string parameter) are never going to happen in PHP. Even C++ looks for an implicit conversion and uses that if available. PHP has well defined implicit conversions between scalars, and there is absolutely no chance that PHP is ever going to implement any form of typing that is more strict than typing in C++. A strict set of scalar types hint that don't juggle anything is just not in the cards.
Second, (bear with me) the form of typing that people seem to have settled on before this RFC was introduced is "the same typing as the core, but at the language level." To use a prior example, the core has:
string substr ( string $string , int $start ){...}
and the following behavior:
substr('foo', 'bar'); // E_WARNING
substr(123, '1'); // '23'
I should be able to write an equivalent:
function my_substr ( string $string , int $start ){..}
and I should get matching behavior:
my_substr('foo', 'bar'); // E_WARNING
my_substr(123, '1'); // '23'
Now here's the point, if somehow this proposal were accepted and incorporated into the language it would make it nearly impossible to later achieve the above. Having both would be confusing, because the behavioral difference is extremely narrow. Your syntax at that point really just silences lossy implicit conversions and would actually be more similar to what one might expect from:
function my_substr ( @string $string, @int $start ){..}
Sure. But I'd argue that anything except foo(int $foo) would have lead to FAR more confusion.
I don't think any other syntax is even an option. This syntax is used by existing type hints in PHP, and in the PHP documentation, and in basically all generated library documentation, and used for parameter types in every syntactically similar language.
This way, it's re-using an existing syntax that every intermediate developer is intimate with, and applying it to a case that's basically functioning along the same lines...
And reusing that syntax leads this straight into the dead end indicated previously when talking about the FC objective.
John Crenshaw
Priacta, Inc.
John,
Thanks a lot for the reply. Comments inline:
You've been spending a lot of time defending these proposals and trying to prove wrong feedback that raises concerns. This is preventing you from actually using the feedback to improve the proposals. You are losing out on perhaps the biggest advantage of the RFC process, which is that multiple minds can work together to hammer out an idea and make it really shine.
I only defended what I thought were misconceptions or miss-information
about them. After all, the quickest way to a failure is assumption
(granted, this is ironic given the rest of this reply)...
You can mince words, but that doesn't change the problem. It is utterly inconsistent with the expectations in creates. You'll argue that it creates an expectation of a type cast, but you'd be wrong in far too many cases. The syntax is similar enough to the syntax for parameter types in other languages that developers will think of it as basically the same thing. The syntax differs however from existing parameter type syntax.
That was intentional. That was the point I was trying to make... But
let's keep going.
The behavioral difference is also a problem, being too different from parameter typing to be useful (it doesn't actually vet the parameter), and yet close enough to validate the confusion (behaves too similarly to an implicit conversion). In the end you have a bizarre syntax that looks like one thing but is conceptually another, but with a subtle behavioral difference that is invisible except when it fails to fail.
Again, up to this point, this fits in with what was intended...
I know about the behavioral difference. I'm not talking about a technical conflict, I'm talking about a conflict in the mind of the developer. Given function(array $a, (array) $b){} the difference between $a and $b is a very advanced distinction and will be completely lost by the average developer.
I actually think that it's not that advanced of a distinction, but
agree to disagree there.
The confusion is made worse by the fact that function(array $a) works, but function(int $a) doesn't, but function((int) $a) does. I know why, but the average developer just learning PHP for the first time won't get it at all.
I won't argue that, but I would make the assertion that there are far
more dangerous things that PHP does that the average developer just
learning PHP won't get. But again, let's go on...
Sometimes I think you miss the point on purpose.
In the docs substr is defined as:
string substr ( string $string , int $start [, int $length ] )If I wanted to write the same thing in my own code I would have to write:
function my_substr ( (string) $string , (int) $start , (int) $length )One syntax for the docs, a different one in my code.
Now, finally we get to a solid point. I didn't make the connection to
the parameter hinting in the docs that you meant. You said "syntax in
the docs", and I was thinking about the casting syntax, which is why I
asserted that both the syntax and the behavior are inline with the
docs.
We were both right, just talking about very different things.
Now, with that said, I completely see your point.
Well, if you argue that this proposal is actually a typecasting enhancement and not a parameter type enhancement, then yes, you'd be right. That's not how this is presented though, that's not where it is presented (Scalar Type Hinting discussion), that's not when it was presented, and that's not how it is getting perceived or measured.
Well, I think that's part of the problem here. People (including both
you and me) have so much vested in this discussion, that they are
reading things into the proposal that aren't there (both in a good
way, and a bad way).
As far as expanding type casting in this way, it doesn't make sense. There is no precedent, it looks and will get treated like parameter hinting (which you are saying it isn't), there is no additional functional value, and very little value of any sort beyond casts (just a tiny documentation boost and a savings in the number of characters in the few cases where a dumb type cast is good enough.)
Well, I think there's a bit more to be gained on both the static
analysis front and the IDE integration front. Additionally, defensive
coding now only needs to worry about 1 type, and it puts the onus to
ensure proper results on the caller (which is where I would argue it
belongs)...
Again, yes, I know that the RFC takes a position on this. My point is not that the RFC doesn't take a position, my point was that the position taken "ignores the need that would have caused this sort of code in the first place."
It took a position, because there seemed to be a fair bit of concensus
on the list (in current and past dicussions) that this sort of thing
should explicitly disallow references. I haven't seen much to the
opposite until:
Reference parameters are basically return values. Just because a parameter will return a value doesn't mean that the type no longer matters. In fact, it means that the calling function should EXPECT the type to change, and EXPECT the value to be modified. One example that occurs to me off hand is preg_match, where the 3rd parameter is documented as an array reference. You can actually pass anything, but it's going to be an array when the function returns.
That's completely fair. But I'd argue that it's also never going to
be consistent, since the cast only relies on the passing of the
variable, not the return:
function foo ((int) &$foo) {
$foo = array();
}
$a = 1;
foo($a);
How the heck did $a become an array, when it was passed as an int?
You can't raise errors like this on lossy casts. Giving a warning if an implicit conversion loses data (123 + '456xyz', or substr('foo', 'bar')) makes sense, but if I explicitly write (int)'456xyz' or (int)23.7, I must not get a warning about data loss (otherwise it would be difficult/impossible to force a deliberately lossy conversion without warnings). Since we can't raise warnings on casts, you really won't be able to do it with casted parameters either (unless you're willing to accept a consistency break). These will be stuck in silence forever.
Absolutely we can. The key is not raising errors on all casts, but
distinguishing between explicit and implicit casts. Explicit casts
always succeed (not sure if that's a good thing IMHO), and implicit
casts error. I would consider passing a variable to a hinted
parameter would count as an implicit cast, since it's happening
after the call begins, which means it would issue an error...
Well, if that is the case, you did not succeed. The FC break you originally worked to avoid is something that can never happen anyway, and this does not avoid the most critical FC break.
Well, then what's the point?
First, "strict" types (in the sense of not allowing an integer to be passed to a string parameter) are never going to happen in PHP. Even C++ looks for an implicit conversion and uses that if available. PHP has well defined implicit conversions between scalars, and there is absolutely no chance that PHP is ever going to implement any form of typing that is more strict than typing in C++. A strict set of scalar types hint that don't juggle anything is just not in the cards.
To be clear, PHP does not have a well defined implicit conversion
between scalars. It has at least 3 of them (actually more, but I'm
not going to count). Doing $a + 1 causes one set of conversions.
Doing substr($a, 0) does another. Doing echo $a does another (yes,
zend_parse_parameters and make_printable_zval have different (albiet
slightly) logic).
Second, (bear with me) the form of typing that people seem to have settled on before this RFC was introduced is "the same typing as the core, but at the language level." To use a prior example, the core has:
string substr ( string $string , int $start ){...}and the following behavior:
substr('foo', 'bar'); //E_WARNING
substr(123, '1'); // '23'I should be able to write an equivalent:
function my_substr ( string $string , int $start ){..}
and I should get matching behavior:
my_substr('foo', 'bar'); //E_WARNING
my_substr(123, '1'); // '23'Now here's the point, if somehow this proposal were accepted and incorporated into the language it would make it nearly impossible to later achieve the above. Having both would be confusing, because the behavioral difference is extremely narrow. Your syntax at that point really just silences lossy implicit conversions and would actually be more similar to what one might expect from:
function my_substr ( @string $string, @int $start ){..}
Fair enough...
Sure. But I'd argue that anything except foo(int $foo) would have lead to FAR more confusion.
I don't think any other syntax is even an option. This syntax is used by existing type hints in PHP, and in the PHP documentation, and in basically all generated library documentation, and used for parameter types in every syntactically similar language.
Now we understand each other fully...
And reusing that syntax leads this straight into the dead end indicated previously when talking about the FC objective.
Point taken.
I've withdrawn the parameter hinting RFC.
I truely thank you for helping me understand your concerns. I only
wish they could have been shared more clearly at the POC phase so we
could have avoided this altogether...
Thanks,
Anthony
Now we understand each other fully...
Point taken.
I've withdrawn the parameter hinting RFC.
Thanks...and aw crap. I hate feeling like I shut the door on something.
Let's make sure we can salvage as much as possible here:
- The structure of the patch looked like it was reusable regardless of whether the final syntax used a typename of a cast, right? Let's not lose that.
- Examining parameters from this perspective gave some good insight into the behavior of the system when implicitly converting inputs.
I truely thank you for helping me understand your concerns. I only wish they could have been shared more clearly at the POC phase so we could have avoided this altogether...
Thanks,
Anthony
I'm sorry for not raising the concerns well enough earlier.
John Crenshaw
Priacta, Inc.
John,
Thanks...and aw crap. I hate feeling like I shut the door on something.
Not at all. I don't feel bad about this in the least. Yes, I would
have liked to have gotten it in, but I want a good solution before I
want mine. So I'm absolutely willing to withdraw this RFC, as it does
have issues.
And it's not really shutting the door. It's moving a roadblock over
so that another (hopefully better) proposal can take its place...
Let's make sure we can salvage as much as possible here:
- The structure of the patch looked like it was reusable regardless of whether the final syntax used a typename of a cast, right? Let's not lose that.
Yeah, there was some in there that I definitely learned from.
Including that the casting logic in the core is really in bad shape
(it's everywhere!).
- Examining parameters from this perspective gave some good insight into the behavior of the system when implicitly converting inputs.
Oh, doing the RFC and the patch definitely had value. It's not like
it's lost effort (and the reference is on the wiki still). And I'm
glad I did a finalized patch, since it showed that some API change (on
C level) would be necessary (namely the argument parsing function, to
accept a double-pointer instead of a single one).
I'm sorry for not raising the concerns well enough earlier.
You did. We just didn't connect and understand each other (or I
didn't understand you) earlier. But that's behind. Let's move up and
on...
So, that leaves the question: where to go next... (I have a somewhat
radical proposal that I'd like to make to list that's somewhat
releated, but I'm going to think it out first before posting)...
Thanks again,
Anthony
Comment in-line below...
Hi,:
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_types
Been watching this for a while, got slightly interested in the parameter
casting thing, but then ran a little test
http://www.roojs.com/examples/types.php
Casting on PHP may help the code inside the function, but the result is
some weird and wonderful magic for the calling code, not to mention that
the docs for (int) casting say the behavior may change, don't expect it
to work like that forever..
You could try some kind of stricter casting. Where odd conversions
between array/object <-> bool/int/float/string do not work on parameter
casting .. but then you end up with two types of casting ...
Anyway, will go back to lurking for a while..
Regards
Alan
Bye
Simon2012/3/6 Kris Craigkris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
Hello,
I came across some info on the web that states that scalar type hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also
be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond
You could try some kind of stricter casting. Where odd conversions
between array/object <-> bool/int/float/string do not work on parameter
casting .. but then you end up with two types of casting ...
I have used in depth the casting operators of C#, which are incredibly
flexible and powerful, and they are based on this exact idea. In C#, there
are two types of casting: implicit and explicit. The first is used for
trivial conversions and the later for the "odd" ones. It is possible to
classify PHP's casts into these two categories:
int to string: implicit
int to float: implicit
int to object: explicit
int to array: explicit
...
Once this classification is done, the code becomes much more sane. Examples:
function test_float( float test ) { ... }
test_float( 1.0 ); // ok
test_float( 1 ); // implicit int to float cast, ok
function test_array( array test ) { ... }
test_array( array() ); // ok
test_array( 1 ); // no implicit int to array cast, error!
test_array( (array)1 ); // explicit int to array cast, ok
I deliberately avoided using Anthony's cast-like syntax, because it does
not fit nicely here. Calling a function may cause an implicit cast, but it
will never do an explicit one.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/7 Alan Knowles alan@akbkhome.com
Comment in-line below...
Hi,:
It got quite around that because we have some RFCs to this where the
functionality seems to be defined as the people thought it should be.
Otherwise they can raise their hands and write a mail that they want to
update the RFC - but as there's no one doing that, I think we're quite
close to what we wanted.Take a look at it and feel free to add your ideas in this thread.
https://wiki.php.net/rfc/parameter_type_casting_hints
https://wiki.php.net/rfc/object_cast_to_typesBeen watching this for a while, got slightly interested in the parameter
casting thing, but then ran a little test
http://www.roojs.com/examples/types.phpCasting on PHP may help the code inside the function, but the result is
some weird and wonderful magic for the calling code, not to mention that
the docs for (int) casting say the behavior may change, don't expect it to
work like that forever..You could try some kind of stricter casting. Where odd conversions between
array/object <-> bool/int/float/string do not work on parameter casting ..
but then you end up with two types of casting ...Anyway, will go back to lurking for a while..
Regards
AlanBye
Simon2012/3/6 Kris Craigkris.craig@gmail.com
Wow no offense, but your timing is terrible, Raymond! We've been going
back and forth on this for the past couple weeks now, though the
discussion
has quieted for the moment.I would suggest you go through some of the recent posts on Internals.
Right now there basically is no solid consensus on this issue, though
some
of us have been working to change that. But as it stands now, I'm not
aware of any plans to introduce expanded typing of any kind in the
foreseeable future. And even if we did, I highly doubt it would happen
before PHP 6.--Kris
On Mon, Mar 5, 2012 at 6:20 PM, Raymond Irvingxwisdom@gmail.com
wrote:Hello,
I came across some info on the web that states that scalar type hinting
was
added to the PHP trunk but it did not make it's way into 5.4 because of
objections from the community. Will it ever make it's way into 5.5?I know PHP is considered to be a weak typed language but it should also
be
about freedom. Freedom for a PHP developer to choose to use scalar type
hinting whenever he/she sees the need.Best regards,
__
Raymond