Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:
Directly apply-able without re2c:
https://gist.github.com/2004623
Removing generated files (requires re2c to compile):
https://gist.github.com/2004650
It's a POC, but it mostly works. There is one known issue: passing a
class implementing __toString to a string hinted function will raise a
segmentation fault. There's also an issue of not separating the
argument on cast yielding to reference whether indicated or not, but
that should be easy to fix (it's just issuing a SEPARATE_IF_NOT_REF in
the cases where it would cast)... I'll work on cleaning it up, but I
wanted to show the concept before investing too much work...
So, basically, there are 4 new parameters:
bool
int
float
string
The casting vs error rules are identical to zend_parse_parameters. So:
function fooi(int $i) { var_dump($i); }
fooi(1); // int(1)
fooi(1.5); // int(1)
fooi("1"); // int(1)
fooi("1abc"); // int(1) + notice about non-well-formed numeric
fooi("foo"); // E_RECOVERABLE_ERROR
fooi(true); // int(1)
fooi(array()); // E_RECOVERABLE_ERROR
fooi($obj); // E_RECOVERABLE_ERROR
function foob(bool $b) { var_dump($b); }
foob(1); // bool(true)
foob(1.5); // bool(true)
foob("1"); // bool(true)
foob("abc"); // bool(true)
foob(true); // bool(true)
foob(array()); // E_RECOVERABLE_ERROR
foob($obj); // E_RECOVERABLE_ERROR
function foos(string $s) { var_dump($s);
foos(1); // string("1")
foos(1.5); // string("1.5")
foos("1"); // string("1")
foos(true); // string("1")
foos(array()); // E_RECOVERABLE_ERROR
foos(new StdClass); // E_RECOVERABLE_ERROR
foos($objImpl__toStringORcast_object); // string(result)
Float works like int, so I won't list it out here...
So, what do you think?
Thanks,
Anthony
Actually, it turns out the segfault and auto-reference bugs were
easier than I thought to fix. I've updated both gists with the new
code, and it looks to be running quite well...
Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:Directly apply-able without re2c:
https://gist.github.com/2004623Removing generated files (requires re2c to compile):
https://gist.github.com/2004650It's a POC, but it mostly works. There is one known issue: passing a
class implementing __toString to a string hinted function will raise a
segmentation fault. There's also an issue of not separating the
argument on cast yielding to reference whether indicated or not, but
that should be easy to fix (it's just issuing a SEPARATE_IF_NOT_REF in
the cases where it would cast)... I'll work on cleaning it up, but I
wanted to show the concept before investing too much work...So, basically, there are 4 new parameters:
bool
int
float
stringThe casting vs error rules are identical to zend_parse_parameters. So:
function fooi(int $i) { var_dump($i); }
fooi(1); // int(1)
fooi(1.5); // int(1)
fooi("1"); // int(1)
fooi("1abc"); // int(1) + notice about non-well-formed numeric
fooi("foo"); //E_RECOVERABLE_ERROR
fooi(true); // int(1)
fooi(array()); //E_RECOVERABLE_ERROR
fooi($obj); //E_RECOVERABLE_ERROR
function foob(bool $b) { var_dump($b); }
foob(1); // bool(true)
foob(1.5); // bool(true)
foob("1"); // bool(true)
foob("abc"); // bool(true)
foob(true); // bool(true)
foob(array()); //E_RECOVERABLE_ERROR
foob($obj); //E_RECOVERABLE_ERROR
function foos(string $s) { var_dump($s);
foos(1); // string("1")
foos(1.5); // string("1.5")
foos("1"); // string("1")
foos(true); // string("1")
foos(array()); //E_RECOVERABLE_ERROR
foos(new StdClass); //E_RECOVERABLE_ERROR
foos($objImpl__toStringORcast_object); // string(result)Float works like int, so I won't list it out here...
So, what do you think?
Thanks,
Anthony
Actually, it turns out the segfault and auto-reference bugs were
easier than I thought to fix. I've updated both gists with the new
code, and it looks to be running quite well...
Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:Directly apply-able without re2c:
https://gist.github.com/2004623Removing generated files (requires re2c to compile):
https://gist.github.com/2004650It's a POC, but it mostly works. There is one known issue: passing a
class implementing __toString to a string hinted function will raise a
segmentation fault. There's also an issue of not separating the
argument on cast yielding to reference whether indicated or not, but
that should be easy to fix (it's just issuing a SEPARATE_IF_NOT_REF in
the cases where it would cast)... I'll work on cleaning it up, but I
wanted to show the concept before investing too much work...So, basically, there are 4 new parameters:
bool
int
float
stringThe casting vs error rules are identical to zend_parse_parameters. So:
function fooi(int $i) { var_dump($i); }
fooi(1); // int(1)
fooi(1.5); // int(1)
fooi("1"); // int(1)
fooi("1abc"); // int(1) + notice about non-well-formed numeric
fooi("foo"); //E_RECOVERABLE_ERROR
fooi(true); // int(1)
fooi(array()); //E_RECOVERABLE_ERROR
fooi($obj); //E_RECOVERABLE_ERROR
function foob(bool $b) { var_dump($b); }
foob(1); // bool(true)
foob(1.5); // bool(true)
foob("1"); // bool(true)
foob("abc"); // bool(true)
foob(true); // bool(true)
foob(array()); //E_RECOVERABLE_ERROR
foob($obj); //E_RECOVERABLE_ERROR
function foos(string $s) { var_dump($s);
foos(1); // string("1")
foos(1.5); // string("1.5")
foos("1"); // string("1")
foos(true); // string("1")
foos(array()); //E_RECOVERABLE_ERROR
foos(new StdClass); //E_RECOVERABLE_ERROR
foos($objImpl__toStringORcast_object); // string(result)Float works like int, so I won't list it out here...
So, what do you think?
Thanks,
Anthony
Anthony,
My concern with this type of patch is that what you are proposing are
not really hints, they are forced casts. As such they modify the data
potentially leading to data loss.
Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:Directly apply-able without re2c:
https://gist.github.com/2004623Removing generated files (requires re2c to compile):
https://gist.github.com/2004650It's a POC, but it mostly works. There is one known issue: passing a
class implementing __toString to a string hinted function will raise a
segmentation fault. There's also an issue of not separating the
argument on cast yielding to reference whether indicated or not, but
that should be easy to fix (it's just issuing a SEPARATE_IF_NOT_REF in
the cases where it would cast)... I'll work on cleaning it up, but I
wanted to show the concept before investing too much work...So, basically, there are 4 new parameters:
bool
int
float
stringThe casting vs error rules are identical to zend_parse_parameters. So:
function fooi(int $i) { var_dump($i); }
fooi(1); // int(1)
fooi(1.5); // int(1)
fooi("1"); // int(1)
fooi("1abc"); // int(1) + notice about non-well-formed numeric
fooi("foo"); //E_RECOVERABLE_ERROR
fooi(true); // int(1)
fooi(array()); //E_RECOVERABLE_ERROR
fooi($obj); //E_RECOVERABLE_ERROR
function foob(bool $b) { var_dump($b); }
foob(1); // bool(true)
foob(1.5); // bool(true)
foob("1"); // bool(true)
foob("abc"); // bool(true)
foob(true); // bool(true)
foob(array()); //E_RECOVERABLE_ERROR
foob($obj); //E_RECOVERABLE_ERROR
function foos(string $s) { var_dump($s);
foos(1); // string("1")
foos(1.5); // string("1.5")
foos("1"); // string("1")
foos(true); // string("1")
foos(array()); //E_RECOVERABLE_ERROR
foos(new StdClass); //E_RECOVERABLE_ERROR
foos($objImpl__toStringORcast_object); // string(result)Float works like int, so I won't list it out here...
So, what do you think?
Thanks,
Anthony
Anthony,
My concern with this type of patch is that what you are proposing are
not really hints, they are forced casts. As such they modify the data
potentially leading to data loss.
But at least it's consistent with "array" and class name qualifiers
that php already has, regardless of what you want to call it, be it
hints, casts, typing, etc.
Anthony,
My concern with this type of patch is that what you are proposing are
not really hints, they are forced casts. As such they modify the data
potentially leading to data loss.
This patch specifically tries to overcome this problem of the previous
version. It will not accept input which will lead to a data loss on
cast. The only exception is passing "123abc" to an int hint, which
will cast to 123 and throw a notice. This is also my only point of
critique: I'd prefer to be stricter here and go all the way to a
recoverable fatal error.
Nikita
On Fri, Mar 9, 2012 at 3:58 AM, Ilia Alshanetsky ilia@prohost.org
wrote:Anthony,
My concern with this type of patch is that what you are proposing
are
not really hints, they are forced casts. As such they modify the
data
potentially leading to data loss.
This patch specifically tries to overcome this problem of the previous
version. It will not accept input which will lead to a data loss on
cast. The only exception is passing "123abc" to an int hint, which
will cast to 123 and throw a notice. This is also my only point of
critique: I'd prefer to be stricter here and go all the way to a
recoverable fatal error.
So what happens to (int) "1233553463645747675685685"
Does it cast and then cause an overflow, which PHP pretty much ignores
and wraps to a negative number?
Or does it error out as you can't convert without mangling the data?
Will it behave differently on 32-bit versus 64-bit hardware for values
that are in-range of 64 but no 32?
--
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FS9NLTNEEKWBE
On Fri, 09 Mar 2012 03:58:52 +0100, Ilia Alshanetsky ilia@prohost.org
wrote:
My concern with this type of patch is that what you are proposing are
not really hints, they are forced casts. As such they modify the data
potentially leading to data loss.
Yes. Just like what happens with internal functions nowadays and this
hasn't been particularly problematic.
That said, I think we could move to a mild BC breaking change for php-next
that would make zpp stricter (with or without user-land scalar type
hinting/coercion).
--
Gustavo Lopes
Am 09.03.2012 09:42, schrieb Gustavo Lopes:
That said, I think we could move to a mild BC breaking change for
php-next that would make zpp stricter (with or without user-land
scalar type hinting/coercion).
A big +1 from me for this change.
Anthony Ferrara wrote:
So, what do you think?
I am a big fan of this style. Accepting e.g. "1abc" as int(1) with a
notice seems like a better solution than anything else. A full error
would be too much towards strict typing (I wouldn't mind personally, but
others do have a strong opinion on this, as we've seen).
The only thing I'm not so crazy about is foob('abc') -> bool(true). I
can live with it, but I don't particularly like it as far as the typing
goes.
Ilia Alshanetsky wrote:
My concern with this type of patch is that what you are proposing are
not really hints, they are forced casts. As such they modify the data
potentially leading to data loss.
I disagree with Ilia on this, as the casts are only made if they can be
converted properly, and give E_RECOVERABLE_ERROR
instead. Anything
that's going to have significant data loss is covered by that.
Bottom line: I'd personally use this, while I certainly would not use
the previous style (with (int) $foo
e.g.).
--
Ryan McCue
<http://ryanmccue.info/
Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:
Thanks for all the hard work you're putting into this :)
So, what do you think?
This is the proposal I like most. It allows for some type juggling,
but blocks off the ugly edge cases where dataloss would occur.
Thinking in that direction I'd say that the casting rules are still
too lax though:
a) I'm not sure that we really want to accept '123abc' on an int cast
with just a notice. In my eyes that is clearly malformed input, which
should not be accepted.
b) The bool cast rules also accept lots of input with dataloss. At
least the fact that "abc" is considered a valid bool seems odd.
Nikita
Hi, all
At first, many thanks to Anthony for writing the code!
2012/3/9 Anthony Ferrara ircmaxell@gmail.com
fooi(1.5); // int(1)
Here an E_NOTICE
would be a minimum as we are modifying the data. I'd
like to see an E_RECOVERABLE_ERROR
as well. You should use
float-casting instead if you want to allow this as well.
And this should be the only difference between int and float. (Float
will of course also accept strings like "1.5")
One more question I have to raise here ... is ".5" a valid float? Or
do I have to change it to "0.5" to get it valid?
2012/3/9 Nikita Popov nikita.ppv@googlemail.com
a) I'm not sure that we really want to accept '123abc' on an int cast
with just a notice. In my eyes that is clearly malformed input, which
should not be accepted.
In my opinion '123abc' is not a valid integer as well.
2012/3/9 Nikita Popov nikita.ppv@googlemail.com
b) The bool cast rules also accept lots of input with dataloss. At
least the fact that "abc" is considered a valid bool seems odd.
I think all values that are not castable to an integer 0 or 1 should
fail in Boolean.
I pretty much like the rest.
But as we are allowing classes implementing __toString() we should
also think about updating the array type-cast - but that's another
discussion that we can pick up later.
Bye
Simon
Overall good job. I would prefer it a little stricter like people already
mention, but it's a step forward definitively with witch I'm totally fine
to live with.
Am 09.03.2012 09:41, schrieb Arvids Godjuks:
Overall good job. I would prefer it a little stricter like people
already
mention, but it's a step forward definitively with witch I'm totally
fine
to live with.
Same from me. Good job.
I like it.
(Now, it would be nice to have another RFC about custom object casting to
int, float and bool...)
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/9 Anthony Ferrara ircmaxell@gmail.com
Hey all,
As promised, I've created a POC patch to implement scalar type hints,
the way that zend_parse_parameters handles hinting. First off, here's
the patch:Directly apply-able without re2c:
https://gist.github.com/2004623Removing generated files (requires re2c to compile):
https://gist.github.com/2004650It's a POC, but it mostly works. There is one known issue: passing a
class implementing __toString to a string hinted function will raise a
segmentation fault. There's also an issue of not separating the
argument on cast yielding to reference whether indicated or not, but
that should be easy to fix (it's just issuing a SEPARATE_IF_NOT_REF in
the cases where it would cast)... I'll work on cleaning it up, but I
wanted to show the concept before investing too much work...So, basically, there are 4 new parameters:
bool
int
float
stringThe casting vs error rules are identical to zend_parse_parameters. So:
function fooi(int $i) { var_dump($i); }
fooi(1); // int(1)
fooi(1.5); // int(1)
fooi("1"); // int(1)
fooi("1abc"); // int(1) + notice about non-well-formed numeric
fooi("foo"); //E_RECOVERABLE_ERROR
fooi(true); // int(1)
fooi(array()); //E_RECOVERABLE_ERROR
fooi($obj); //E_RECOVERABLE_ERROR
function foob(bool $b) { var_dump($b); }
foob(1); // bool(true)
foob(1.5); // bool(true)
foob("1"); // bool(true)
foob("abc"); // bool(true)
foob(true); // bool(true)
foob(array()); //E_RECOVERABLE_ERROR
foob($obj); //E_RECOVERABLE_ERROR
function foos(string $s) { var_dump($s);
foos(1); // string("1")
foos(1.5); // string("1.5")
foos("1"); // string("1")
foos(true); // string("1")
foos(array()); //E_RECOVERABLE_ERROR
foos(new StdClass); //E_RECOVERABLE_ERROR
foos($objImpl__toStringORcast_object); // string(result)Float works like int, so I won't list it out here...
So, what do you think?
Thanks,
Anthony
(Now, it would be nice to have another RFC about custom object casting to
int, float and bool...)
You mean like https://wiki.php.net/rfc/object_cast_to_types which is
still in draft?
Note that __toBool would be problematic, since it would be called if
the object was used in an if statement, which could yield some very
strange results if it returned false (it would break the existing
semantics about how we can use if statements to determine if the type
is populated)...
Anthony
(Now, it would be nice to have another RFC about custom object casting
to int, float and bool...)You mean like https://wiki.php.net/rfc/object_cast_to_types which is still in draft?
Note that __toBool would be problematic, since it would be called if the object was used in an if statement, which could yield some very strange results if it returned false (it would break the existing semantics about how we can use if statements to determine if the type is populated)...
Anthony
And yet, __toBool probably sits right next to __toArray in terms of the level of usefulness (maybe even beats it.) isset() can always be used to determine whether something was ACTUALLY set to a non-null value, and to some extent there is already a semantic problem anyway since things like if("0") resolve to false.
John Crenshaw
Priacta, Inc.
John,
And yet, __toBool probably sits right next to __toArray in terms of the level of usefulness (maybe even beats it.) isset() can always be used to determine whether something was ACTUALLY set to a non-null value, and to some extent there is already a semantic problem anyway since things like if("0") resolve to false.
The original proposal was to include toBool functionality. Stas was
one who strongly opposed it which is one of the reasons that I removed
it.
However, if a convincing case can be made to add it in, and there's
enough buy in, I would love to see it added. My issue is that I don't
want the whole proposal rejected because of that one method... But
that's what a RFC process is for, so let's get discussing...
Thanks,
Anthony
Yes, like that, only better. Since automatic type casting is central in
PHP, as this is evident after all this discussion, I believe that it should
be better supported. There are two thinks that I would like to see here:
- No more magic methods, please.
- It should cover (eventually) casting to and from any type.
:-)
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/9 Anthony Ferrara ircmaxell@gmail.com
(Now, it would be nice to have another RFC about custom object casting to
int, float and bool...)You mean like https://wiki.php.net/rfc/object_cast_to_types which is
still in draft?Note that __toBool would be problematic, since it would be called if
the object was used in an if statement, which could yield some very
strange results if it returned false (it would break the existing
semantics about how we can use if statements to determine if the type
is populated)...Anthony
2012/3/9 Lazare Inepologlou linepogl@gmail.com
Yes, like that, only better. Since automatic type casting is central in
PHP, as this is evident after all this discussion, I believe that it
should
be better supported. There are two thinks that I would like to see here:
- No more magic methods, please.
- It should cover (eventually) casting to and from any type.
:-)
Lazare INEPOLOGLOU
Ingénieur Logiciel
Hi, Lazare
As you mentioned it in another thread, I like the idea of C# you described ...
Draw a line between explicit and implicit casting.
What the current idea would be is an implicit casting (as I understood
it right).
Let me just repeat your examples:
2012/3/7 Lazare Inepologlou linepogl@gmail.com
function test_float( float test ) { ... }
test_float( 1.0 ); // ok
test_float( 1 ); // implicit int to float cast, okfunction 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
An explicit type-cast should be always possible and try to get the
very last bit of useful information out of the given bunch. Here it
makes sense to have magic functions for integer, float, string etc.
But as we're here talking about an implicit casting when passing a
class to a function, I don't like the idea of calling the
magic-functions if you paste a class in here as it changes the content
of the variable. This won't make it easy passing a variable as
reference. If you just switch to another type, you can afterwards do
whatever you was able to do before.
Bye
Simon
What the current idea would be is an implicit casting (as I understood it
right).
Yes, exactly.
This won't make it easy passing a variable as reference.
Type casting combined with passing by reference is problematic in many
ways. Just an example:
fuction foo( string & $buffer) { ... }
foo( $my_buffer );
Here, $my_buffer has just been declared, so it is null. Should this be an
error? I don't know! So, I think that that passing by reference should not
be (immediately) supported.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/9 Simon Schick simonsimcity@googlemail.com
2012/3/9 Lazare Inepologlou linepogl@gmail.com
Yes, like that, only better. Since automatic type casting is central in
PHP, as this is evident after all this discussion, I believe that it
should
be better supported. There are two thinks that I would like to see here:
- No more magic methods, please.
- It should cover (eventually) casting to and from any type.
:-)
Lazare INEPOLOGLOU
Ingénieur LogicielHi, Lazare
As you mentioned it in another thread, I like the idea of C# you described
...
Draw a line between explicit and implicit casting.What the current idea would be is an implicit casting (as I understood
it right).
Let me just repeat your examples:2012/3/7 Lazare Inepologlou linepogl@gmail.com
function test_float( float test ) { ... }
test_float( 1.0 ); // ok
test_float( 1 ); // implicit int to float cast, okfunction 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, okAn explicit type-cast should be always possible and try to get the
very last bit of useful information out of the given bunch. Here it
makes sense to have magic functions for integer, float, string etc.But as we're here talking about an implicit casting when passing a
class to a function, I don't like the idea of calling the
magic-functions if you paste a class in here as it changes the content
of the variable. This won't make it easy passing a variable as
reference. If you just switch to another type, you can afterwards do
whatever you was able to do before.Bye
Simon
2012/3/9 Lazare Inepologlou linepogl@gmail.com
Type casting combined with passing by reference is problematic in many ways. Just an example:
fuction foo( string & $buffer) { ... }
foo( $my_buffer );Here, $my_buffer has just been declared, so it is null. Should this be an error? I don't know! So, I think that that passing by reference should not be (immediately) supported.
Hi, Lazare
This should at least throw an E_NOTICE
:) And also an error as NULL
is
not allowed here.
Let me modify your example:
fuction foo( string & $buffer = NULL) { ... }
foo( $my_buffer );
This would only raise the E_NOTICE
because the variable has not been declared.
Or would you say that NULL
is equal with an empty string (talking
about implicit casting)? I would not like that, but if, don't let it
be (int)0 or (bool)false as well.
Bye
Simon
From: Simon Schick [mailto:simonsimcity@googlemail.com]
2012/3/9 Lazare Inepologlou linepogl@gmail.com
Type casting combined with passing by reference is problematic in many ways. Just an example:
fuction foo( string & $buffer) { ... } foo( $my_buffer );
Here, $my_buffer has just been declared, so it is null. Should this be an error? I don't know! So, I think that that passing by reference should not be (immediately) supported.
Hi, Lazare
This should at least throw an
E_NOTICE
:) And also an error asNULL
is not allowed here.Let me modify your example:
fuction foo( string & $buffer = NULL) { ... } foo( $my_buffer );
This would only raise the
E_NOTICE
because the variable has not been declared.
Or would you say thatNULL
is equal with an empty string (talking about implicit casting)? I would not like that, but if, don't let it be (int)0 or (bool)false as well.Bye
Simon
The reason you have to validate the input type in this case is because even though it is a reference, we don't ACTALLY know that it isn't supposed to contain an input (even though that would be against all sane rules most of the time).
I'm not attached to this idea at all, but I thought I'd throw it out and see if anyone can think of a problem with it; what if we added extra out and inout hints for references?
// So this would give no error at all. Parameter is anticipated to be for output. Just silently change the type and don't warn on anything.
fuction foo( out string & $buffer) { ... } foo( $my_buffer );
// This WOULD give an error, because the parameter is also an input parameter:
fuction foo( inout string & $buffer = NULL) { ... } foo( $my_buffer );
// In any case no errors on these:
fuction foo( inout string & $buffer = NULL) { ... } foo( (string)$my_buffer );
fuction foo( string & $buffer = NULL) { ... } foo( (string)$my_buffer );
If we assumed that all references were out unless stated otherwise we could avoid reserving an "out" keyword, and only add "inout", which is unlikely to conflict with stuff.
Like I said, no attachment to this at all. My gut tells me I may have missed something really stupid here. Just brainstorming.
John Crenshaw
Priacta, Inc.
what if we added extra out and inout hints for references?
With the danger of becoming boring, I have to say that C# also support
"ref" and "out" arguments... Are we reinventing the wheel here?
To be honest, this is going too far. Can we have the basics first? Passing
by reference is a corner case, at least for PHP.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/9 John Crenshaw johncrenshaw@priacta.com
From: Simon Schick [mailto:simonsimcity@googlemail.com]
2012/3/9 Lazare Inepologlou linepogl@gmail.com
Type casting combined with passing by reference is problematic in many
ways. Just an example:fuction foo( string & $buffer) { ... } foo( $my_buffer );
Here, $my_buffer has just been declared, so it is null. Should this be
an error? I don't know! So, I think that that passing by reference should
not be (immediately) supported.Hi, Lazare
This should at least throw an
E_NOTICE
:) And also an error asNULL
is
not allowed here.Let me modify your example:
fuction foo( string & $buffer = NULL) { ... } foo( $my_buffer );
This would only raise the
E_NOTICE
because the variable has not been
declared.
Or would you say thatNULL
is equal with an empty string (talking about
implicit casting)? I would not like that, but if, don't let it be (int)0 or
(bool)false as well.Bye
SimonThe reason you have to validate the input type in this case is because
even though it is a reference, we don't ACTALLY know that it isn't supposed
to contain an input (even though that would be against all sane rules most
of the time).I'm not attached to this idea at all, but I thought I'd throw it out and
see if anyone can think of a problem with it; what if we added extra out
and inout hints for references?// So this would give no error at all. Parameter is anticipated to be for
output. Just silently change the type and don't warn on anything.
fuction foo( out string & $buffer) { ... } foo( $my_buffer );// This WOULD give an error, because the parameter is also an input
parameter:
fuction foo( inout string & $buffer = NULL) { ... } foo( $my_buffer );// In any case no errors on these:
fuction foo( inout string & $buffer = NULL) { ... } foo(
(string)$my_buffer );
fuction foo( string & $buffer = NULL) { ... } foo( (string)$my_buffer );If we assumed that all references were out unless stated otherwise we
could avoid reserving an "out" keyword, and only add "inout", which is
unlikely to conflict with stuff.Like I said, no attachment to this at all. My gut tells me I may have
missed something really stupid here. Just brainstorming.John Crenshaw
Priacta, Inc.
To be honest, this is going too far. Can we have the basics first? Passing by reference is a corner case, at least for PHP.
RFCs die on ignored corner cases. IMO it's worth at least considering whether there is a viable solution. The most common cases would be resolved easily if we always allow null to be passed (whether we allow it to juggle, or allow actually passing a null value through), since the inputs used in these cases would almost always either be null, or already have a matching type (in the case of inout). This edge case may have edge cases though...
John Crenshaw
Priacta, Inc.
John,
The reason you have to validate the input type in this case is because even though it is a reference, we don't ACTALLY know that it isn't supposed to contain an input (even though that would be against all sane rules most of the time).
Well, we don't know, but I'd argue do we really care? If they passed
a different type that's going to get casted away, that's their
problem. They passed it to the hint. Now, if you're talking about
object cast sementics, that raises a whole different ballgame. That's
something that we should consider...
I'm not attached to this idea at all, but I thought I'd throw it out and see if anyone can think of a problem with it; what if we added extra out and inout hints for references?
// So this would give no error at all. Parameter is anticipated to be for output. Just silently change the type and don't warn on anything.
fuction foo( out string & $buffer) { ... } foo( $my_buffer );// This WOULD give an error, because the parameter is also an input parameter:
fuction foo( inout string & $buffer = NULL) { ... } foo( $my_buffer );
Why would NULL
give an error under any circumstance? You defaulted it
to null. So why should passing a NULL
parameter in its place be any
different than not passing a first argument? In fact, erroring on
that would greatly reduce utility, since what if I wanted to set the
2nd parameter only? I can no longer pass NULL
(even though it's a
valid default), and have to change the first parameter. Big
regression if you ask me...
// In any case no errors on these:
fuction foo( inout string & $buffer = NULL) { ... } foo( (string)$my_buffer );
fuction foo( string & $buffer = NULL) { ... } foo( (string)$my_buffer );
Actually, these SHOULD cause errors (and do). Because they will not
do what you expect. The cast causes a temporary variable to be
created in opcode. And you can't pass a temporary variable by
reference: http://codepad.viper-7.com/wLBSkS
If we assumed that all references were out unless stated otherwise we could avoid reserving an "out" keyword, and only add "inout", which is unlikely to conflict with stuff.
I still fail to see the purpose. Both will cause a cast (since the
value required on the other end needs to be initialized to the proper
type). The only difference is that one throws an error on invalid
cast, and the other doesn't. Seems to be to just be un-necessary
added complexity (but feel free to convince me otherwise, I love to be
convinced wrong)...
Like I said, no attachment to this at all. My gut tells me I may have missed something really stupid here. Just brainstorming.
Oh absolutely. And brainstoring is good!
Thanks,
Anthony
The reason you have to validate the input type in this case is because
even though it is a reference, we don't ACTALLY know that it isn't
supposed to contain an input (even though that would be against all
sane rules most of the time).
Last time I checked, two consecutive "exec" calls with the same second
argument would append to the array of outputs.
Hey, it's even documented that way:
http://www.php.net/manual/en/function.exec.php
It was unexpected when I first saw it, but seemed perfectly sane to
me, as I suppose somebody might want it, and unset($output); wasn't
exactly horrible to add before each "exec" call.
It would be wise to check other PHP function with references returned
to sanity check your definition of sane :-)
--
brain cancer update:
http://richardlynch.blogspot.com/search/label/brain%20tumor
Donate:
https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FS9NLTNEEKWBE
Lazare,
This won't make it easy passing a variable as reference.
Type casting combined with passing by reference is problematic in many ways.
No it's not. The core functionality does it quite fine, and it uses
typed parameters...
Just an example:
fuction foo( string & $buffer) { ... }
foo( $my_buffer );Here, $my_buffer has just been declared, so it is null. Should this be an
error? I don't know! So, I think that that passing by reference should not
be (immediately) supported.
This one one where my wants are superseded by existing functionality.
The current implementation has a definite answer to that. And the
answer is that no, no notice is raised. Plenty of people are using it
to that effect right now. Check out this abomination:
http://stackoverflow.com/questions/9636052/is-there-a-way-to-pass-an-undeclared-variable-to-a-function-without-notice/9636395#9636395
However, it's also quite useful. Look at your code base. Whenever
you call preg_match with the third parameter, do you always
initialize the $match parameter? And do you always make sure it's
an array? The chances are very likely (based on a lot of the code
I've seen), no.
This functionality is very pervasive to the core, and we shouldn't go
changing it now (even implementing user-land pass-by-reference). Not
supporting references is one thing, but changing the semantics of it
is a completely different talk...
Anthony
Type casting combined with passing by reference is problematic in many
ways. Just an example:fuction foo( string & $buffer) { ... }
foo( $my_buffer );Here, $my_buffer has just been declared, so it is null. Should this be an
error? I don't know! So, I think that that passing by reference should not
be (immediately) supported.
Strictly speaking, if you add a type to a referenced variable in that way it's only logical that you expect it to have a proper value when the function is called. After all, it's not an output type declaration :)
Ok, so it looks like we've had some decent conversation, but it has
started to tail off a bit. I'd normally draft an RFC at this point,
but it seems there's still some contention on how exactly the
implementation should work.
Personally, if we're going to go for any form of strict checking
(meaning not blind-conversion), I will not support these hint rules
diverging from zend_parse_parameters (internal functions). It just
creates a new layer of inconvenience and confusion for not a whole lot
of gain. When I say divergence from ZPP, I'm talking about the same
behavior when ZPP returns SUCCESS, and a E_RECOVERABLE_ERROR
when ZPP
returns FAILURE...
Now, with that said, I'd be all for making sane changes to ZPP to
bring both inline with a common goal. Think that passing "1abc" to an
int type hinted parameter (which currently raises a notice) is
unacceptable? Then my opinion is that it should be tightened in both
places at the same time. But they should stay connected as closely as
possible for consistency...
So, with that said, let me ask this question: What needs to change
from the current POC before it can be formalized into an RFC? Do we
need to tighten the conversions? Or are they OK as-is?
Thoughts?
Anthony
On Sat, Mar 10, 2012 at 2:45 AM, Tjerk Meesters
tjerk.meesters@gmail.com wrote:
Type casting combined with passing by reference is problematic in many
ways. Just an example:fuction foo( string & $buffer) { ... }
foo( $my_buffer );Here, $my_buffer has just been declared, so it is null. Should this be an
error? I don't know! So, I think that that passing by reference should not
be (immediately) supported.Strictly speaking, if you add a type to a referenced variable in that way it's only logical that you expect it to have a proper value when the function is called. After all, it's not an output type declaration :)
I should point out that returning false on param parsing failure on the
language level is one thing (not to mention it's not ok to do that in the
first place by my taste), but forcing that behavior on the user-land level
is kind'a too much.
Consider how the code will become much more complicated - now you have to
not only to check what you pass to the functions, but you have to check
what it returns every single time (do I have to mention that false can be
never returned by the function at all except when the param parsing fails?).
What is consistent and exists on the internal language layer
not necessarily good for the user-land. I'm kind'a surprised no one thought
of that.
As I said I can live with the throwing notices and warnings (and not
E_RECOVERABLE_ERROR
as I personally wanted), but returning false even not
trying to run the function is just a bad idea all over the place.
2012/3/12 Anthony Ferrara ircmaxell@gmail.com
Ok, so it looks like we've had some decent conversation, but it has
started to tail off a bit. I'd normally draft an RFC at this point,
but it seems there's still some contention on how exactly the
implementation should work.Personally, if we're going to go for any form of strict checking
(meaning not blind-conversion), I will not support these hint rules
diverging from zend_parse_parameters (internal functions). It just
creates a new layer of inconvenience and confusion for not a whole lot
of gain. When I say divergence from ZPP, I'm talking about the same
behavior when ZPP returns SUCCESS, and aE_RECOVERABLE_ERROR
when ZPP
returns FAILURE...Now, with that said, I'd be all for making sane changes to ZPP to
bring both inline with a common goal. Think that passing "1abc" to an
int type hinted parameter (which currently raises a notice) is
unacceptable? Then my opinion is that it should be tightened in both
places at the same time. But they should stay connected as closely as
possible for consistency...So, with that said, let me ask this question: What needs to change
from the current POC before it can be formalized into an RFC? Do we
need to tighten the conversions? Or are they OK as-is?Thoughts?
Anthony
On Sat, Mar 10, 2012 at 2:45 AM, Tjerk Meesters
tjerk.meesters@gmail.com wrote:On 9 Mar, 2012, at 11:20 PM, Lazare Inepologlou linepogl@gmail.com
wrote:Type casting combined with passing by reference is problematic in many
ways. Just an example:fuction foo( string & $buffer) { ... }
foo( $my_buffer );Here, $my_buffer has just been declared, so it is null. Should this be
an
error? I don't know! So, I think that that passing by reference should
not
be (immediately) supported.Strictly speaking, if you add a type to a referenced variable in that
way it's only logical that you expect it to have a proper value when the
function is called. After all, it's not an output type declaration :)
Arvids,
On Mon, Mar 12, 2012 at 4:39 AM, Arvids Godjuks
arvids.godjuks@gmail.com wrote:
I should point out that returning false on param parsing failure on the
language level is one thing (not to mention it's not ok to do that in the
first place by my taste), but forcing that behavior on the user-land level
is kind'a too much.
To be clear, that's not what I had meant at all. I was talking about
ZPP returning false internally, not what the internal functions
themselves do (it's up to them to ignore the error, to go on, or raise
a different error).
Consider how the code will become much more complicated - now you have to
not only to check what you pass to the functions, but you have to check what
it returns every single time (do I have to mention that false can be never
returned by the function at all except when the param parsing fails?).
I agree 100%. There's also a semantic difference between an error
state from the function and an error state from parameter parsing.
Which is why an E_RECOVERABLE_ERROR
is my preferred state, since it
communicates the information properly...
What is consistent and exists on the internal language layer
not necessarily good for the user-land. I'm kind'a surprised no one thought
of that.
As I said I can live with the throwing notices and warnings (and not
E_RECOVERABLE_ERROR
as I personally wanted), but returning false even not
trying to run the function is just a bad idea all over the place.
I'm confused. Do you not want E_RECOVERABLE_ERROR
for parameter
failures? Or do you, but could live with lesser as well? I didn't
quite get that part...
Anthony
What is consistent and exists on the internal language layer
not necessarily good for the user-land. I'm kind'a surprised no one
thought
of that.
As I said I can live with the throwing notices and warnings (and not
E_RECOVERABLE_ERROR
as I personally wanted), but returning false even not
trying to run the function is just a bad idea all over the place.I'm confused. Do you not want
E_RECOVERABLE_ERROR
for parameter
failures? Or do you, but could live with lesser as well? I didn't
quite get that part...Anthony
Hi Anthony.
Yea, that part looks confusing.
What I wanted to say is that I would like to get E_RECOVERABLE_ERROR
and I
was voicing my opinion on that earlier in the threads. But I could live
with E_WARNING
and E_NOTICE
if community decides it to be less strict - I
will clean up my code not to throw a single notice (and because I use Yii -
it's by default converts any E_* raised to a fatal error and throws HTTP
500 error via exceptions).
In my 8 years of active PHP development I learned that some strictness in
deep core code of the project is a good thing and erroring the hell out
there makes perfect sense. It's a delicate balance and I never apply it to
the level that does actual communication with the outside world.
Arvids,
Yea, that part looks confusing.
What I wanted to say is that I would like to getE_RECOVERABLE_ERROR
and I
was voicing my opinion on that earlier in the threads. But I could live with
E_WARNING
andE_NOTICE
if community decides it to be less strict - I will
clean up my code not to throw a single notice (and because I use Yii - it's
by default converts any E_* raised to a fatal error and throws HTTP 500
error via exceptions).In my 8 years of active PHP development I learned that some strictness in
deep core code of the project is a good thing and erroring the hell out
there makes perfect sense. It's a delicate balance and I never apply it to
the level that does actual communication with the outside world.
Ok, I agree 100%. I was just confused about your wording and wanted
to clarify it to the list. So we're on the same page here.
Thanks!
Anthony
Hello Anthony,
I will raise once again the question about accepting null. According to
your POC, null is an acceptable value if it is also declared as a default
value. This is problematic for the scalar types, because they can very well
have a different default value.
An example: There is a check box with three states (check, unchecked and
mixed). This is usually translated to a three state boolean (true, false
and null). The default value of the check box is false.
function set_check_box_state( bool state = false ) { ... }
set_check_box_state( null ); // null will be converted to false here...
Therefore, this cannot work, unless the default value becomes null, which
is against the requirements. What I suggest is something like this:
function set_check_box_state( bool? state = false ) { ... }
set_check_box_state( null ); // works fine
In my opinion this is much clearer, as it separates the notions of the type
and that of the default value.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/12 Lazare Inepologlou linepogl@gmail.com
function set_check_box_state( bool state = false ) { ... }
set_check_box_state( null ); // null will be converted to false here...Therefore, this cannot work, unless the default value becomes null, which
is against the requirements. What I suggest is something like this:function set_check_box_state( bool? state = false ) { ... }
set_check_box_state( null ); // works fineIn my opinion this is much clearer, as it separates the notions of the
type
and that of the default value.Lazare INEPOLOGLOU
Ingénieur Logiciel
Hi Lazare,
I'd like to keep the accptance of null as it is for classes and arrays.
Here's an example I wrote earlier:
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 new
feature we're discussing here.
function foo(int $d = 20) { var_dump($d); }
foo(null); // This should then also simply fail. Don't care about
what's the default-value or defined type.
function foo(int $d = null) { var_dump($d); }
foo(null); // And this should pass it through, providing the
NULL-value in the function.
function foo(int $d = 20) { var_dump($d); }
foo( (int)null ); // This can provide 0 as the programmer forcing it
to be an integer before putting it into this function-call.
I would personally not like to give the user the option to set a
null-value if it's not the default.
But .. I don't wanna screw up your idea.
Bye
Simon
I think that the "null issue" is not an issue. Strictly speaking if you
want null or an int - leave out the type hint and use generic argument that
will accept anything.
I think it's over-engineering to try and push a special treatment for the
null. If function/method argument accepts anything but a single type -
it's type-less and does not need a type hint.
Developers should not abuse type hints and adding a special case for
handling null will make many start to request things like this:
function foo(string|array $data)
function foo(bool|int $flag)
function foo(mixed $someVar)
etc.
I'm not sure about you, but I don't wanna see that kind of thing eventually
making it's way into the language (believe me - even I considered that at
some point, but i'm more mature now and more settled in my wishes :))
I'm not sure about you, but I don't wanna see that kind of thing
eventually making it's way into the language
Me neither. All I am saying is that, since int|null is already here from
the back door, I think it should be properly supported.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/12 Arvids Godjuks arvids.godjuks@gmail.com
I think that the "null issue" is not an issue. Strictly speaking if you
want null or an int - leave out the type hint and use generic argument that
will accept anything.
I think it's over-engineering to try and push a special treatment for the
null. If function/method argument accepts anything but a single type -
it's type-less and does not need a type hint.Developers should not abuse type hints and adding a special case for
handling null will make many start to request things like this:
function foo(string|array $data)
function foo(bool|int $flag)
function foo(mixed $someVar)
etc.I'm not sure about you, but I don't wanna see that kind of thing
eventually making it's way into the language (believe me - even I
considered that at some point, but i'm more mature now and more settled in
my wishes :))
2012/3/12 Lazare Inepologlou linepogl@gmail.com
I'm not sure about you, but I don't wanna see that kind of thing
eventually making it's way into the languageMe neither. All I am saying is that, since int|null is already here from
the back door, I think it should be properly supported.
There is no int|null at the moment, and should not be. You can pass
anything - object, array, string, bool, int, float resource, callable -
they all are accepted and are checked in function body if it's writer wrote
that code.
Hint should provide a hint for a single type, or hint doesn't belong there.
Hello Arvids,
The patch of Anthony, clearly states that this is accepted:
function foo ( int $bar = null ) { }
And this is what I called an int|null.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/12 Arvids Godjuks arvids.godjuks@gmail.com
2012/3/12 Lazare Inepologlou linepogl@gmail.com
I'm not sure about you, but I don't wanna see that kind of thing
eventually making it's way into the languageMe neither. All I am saying is that, since int|null is already here from
the back door, I think it should be properly supported.There is no int|null at the moment, and should not be. You can pass
anything - object, array, string, bool, int, float resource, callable -
they all are accepted and are checked in function body if it's writer wrote
that code.
Hint should provide a hint for a single type, or hint doesn't belong there.
Lazare,
The patch of Anthony, clearly states that this is accepted:
function foo ( int $bar = null ) { }
And this is what I called an int|null.
Yup, it does. Because that's the current behavior with array and
object casting. If you default it to null in the declaration, null is
a valid value. If you don't, it's not...
Thank you for the confirmation.
What I am saying here is that, although this behavior was fine for objects,
it is not enough for scalars. One of the main arguments in favor of the
adoption of this syntax was that null was the only possible default value
for objects anyway. This obviously is not the case with for scalar types.
This is why I suggest a different syntax (which can also be used by object
types for consistency).
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/12 Anthony Ferrara ircmaxell@gmail.com
Lazare,
The patch of Anthony, clearly states that this is accepted:
function foo ( int $bar = null ) { }
And this is what I called an int|null.
Yup, it does. Because that's the current behavior with array and
object casting. If you default it to null in the declaration, null is
a valid value. If you don't, it's not...
--f46d0442880e02b97f04bb0b432b
Content-Type: text/plain; charset=UTF-8I think that the "null issue" is not an issue. Strictly speaking if you
want null or an int - leave out the type hint and use generic argument that
will accept anything.
I think it's over-engineering to try and push a special treatment for the
null. If function/method argument accepts anything but a single type -
it's type-less and does not need a type hint.
However, that conflicts with how typehints work currently in PHP:
public function setContainer(Container $container = null)
{
$this->container = $container;
}
This is perfectly valid currently, and allows "unsetting" a value
easily. I'd expect scalar hints to work exactly the same way -- in other
words, null, or a value that satisfies the hint.
--
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
Hello Simon,
First of all, none of your examples cover the case I mentioned, and so, my
concerns are still valid.
Secondly, you make some wrong assumptions about how this specific POC
works. For example, you write:
function foo(int $d = 20) { var_dump($d); }
foo(null); // This should then also simply fail.
Unless I am wrong, the patch will convert null to 0.
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/12 Simon Schick simonsimcity@googlemail.com
2012/3/12 Lazare Inepologlou linepogl@gmail.com
function set_check_box_state( bool state = false ) { ... }
set_check_box_state( null ); // null will be converted to false here...Therefore, this cannot work, unless the default value becomes null, which
is against the requirements. What I suggest is something like this:function set_check_box_state( bool? state = false ) { ... }
set_check_box_state( null ); // works fineIn my opinion this is much clearer, as it separates the notions of the
type
and that of the default value.Lazare INEPOLOGLOU
Ingénieur LogicielHi Lazare,
I'd like to keep the accptance of null as it is for classes and arrays.
Here's an example I wrote earlier: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 new
feature we're discussing here.function foo(int $d = 20) { var_dump($d); }
foo(null); // This should then also simply fail. Don't care about
what's the default-value or defined type.function foo(int $d = null) { var_dump($d); }
foo(null); // And this should pass it through, providing the
NULL-value in the function.function foo(int $d = 20) { var_dump($d); }
foo( (int)null ); // This can provide 0 as the programmer forcing it
to be an integer before putting it into this function-call.I would personally not like to give the user the option to set a
null-value if it's not the default.
But .. I don't wanna screw up your idea.Bye
Simon
Lazare,
Yes, like that, only better. Since automatic type casting is central in PHP,
as this is evident after all this discussion, I believe that it should be
better supported. There are two thinks that I would like to see here:
- No more magic methods, please.
Any particular reason? If the magic is useful, why not add the
ability? I'm not saying we should get to python level with the shear
number of magic methods, but to artificially limit when useful
behavior can be added... I'm not so sure...
- It should cover (eventually) casting to and from any type.
This doesn't? What other types (except from other classes) would you
like to see (or could we do besides resource and null)???
Anthony
What other types (except from other classes)...
I was talking about other classes... Of course, this does not have to be
implemented right now, but the syntax should not close the door for
something like that in the future.
If the magic is useful, why not add the ability?
Because it is ugly and limited. All the resent discussion resulted to the
fact that type casting is one of the central features of PHP that we cannot
live without. So I think that the mechanism to expand type casting should
be promoted, even with some special new syntax.
:-)
Lazare INEPOLOGLOU
Ingénieur Logiciel
2012/3/9 Anthony Ferrara ircmaxell@gmail.com
Lazare,
On Fri, Mar 9, 2012 at 8:54 AM, Lazare Inepologlou linepogl@gmail.com
wrote:Yes, like that, only better. Since automatic type casting is central in
PHP,
as this is evident after all this discussion, I believe that it should be
better supported. There are two thinks that I would like to see here:
- No more magic methods, please.
Any particular reason? If the magic is useful, why not add the
ability? I'm not saying we should get to python level with the shear
number of magic methods, but to artificially limit when useful
behavior can be added... I'm not so sure...
- It should cover (eventually) casting to and from any type.
This doesn't? What other types (except from other classes) would you
like to see (or could we do besides resource and null)???Anthony