Hey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.
It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.
Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
I think this is a great proposal.
I have one question, however. Though I doubt it would be a frequent
usage, would { function (StdClass[][] $x) {} } work, for representing an
array of arrays?
Andrea Faulds
http://ajf.me/
Hey,
-----Original Message-----
From: Philip Sturgeon [mailto:pjsturgeon@gmail.com]
Sent: Wednesday, January 15, 2014 7:18 PM
To: internals@lists.php.net
Subject: [PHP-DEV] Introducing "Array Of" RFCHey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.--
First of all, I really like the RFC, good idea, well done.
But about some details. I am not sure if I got the implementation right (haven't done any code contributions so far, so
I am not really familiar with the source code) but it seems that a check for NULL
is implemented for the actual
parameter which is perfectly fine (done for other type hints as well) but it also checks if all members of an array are
not NULL
and the check returns a failure if NULL
is detected. I think that's wrong, NULL
is a perfect valid entry in an
array.
Furthermore, what about type hints like the following ones:
function foo(int[] $qualities, callable[] $callables){}
Seems like they are not supported. But might be that I am totally wrong and did not understand the code
But about some details. I am not sure if I got the implementation right (haven't done any code contributions so far, so
I am not really familiar with the source code) but it seems that a check forNULL
is implemented for the actual
parameter which is perfectly fine (done for other type hints as well) but it also checks if all members of an array are
notNULL
and the check returns a failure ifNULL
is detected. I think that's wrong,NULL
is a perfect valid entry in an
array.
I agree with this. NULL
should be considered a valid substitute for a
value of any type.
--
Andrea Faulds
http://ajf.me/
Furthermore, what about type hints like the following ones:
function foo(int[] $qualities, callable[] $callables){}Seems like they are not supported. But might be that I am totally wrong and did not understand the code
Please forget about my question about type hint for int[], I forgot for a second that PHP does not support scalar type
hints.
However, the question about callable[] remains
Hey,
-----Original Message-----
From: Philip Sturgeon [mailto:pjsturgeon@gmail.com]
Sent: Wednesday, January 15, 2014 7:18 PM
To: internals@lists.php.net
Subject: [PHP-DEV] Introducing "Array Of" RFCHey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.--
First of all, I really like the RFC, good idea, well done.
But about some details. I am not sure if I got the implementation right (haven't done any code contributions so far, so
I am not really familiar with the source code) but it seems that a check forNULL
is implemented for the actual
parameter which is perfectly fine (done for other type hints as well) but it also checks if all members of an array are
notNULL
and the check returns a failure ifNULL
is detected. I think that's wrong,NULL
is a perfect valid entry in an
array.Furthermore, what about type hints like the following ones:
function foo(int[] $qualities, callable[] $callables){}Seems like they are not supported. But might be that I am totally wrong and did not understand the code
Ok, ignoring the int stuff as PHP doesn't generally do that. We don't
want to broach that topic here.
As for allowing null, this feature is currently intended as a
syntactic representation of:
foreach ($foos as $foo) {
if (! $foo instanceof Face) {
throw new Exception ('AAAGGGGGHHH!');
}
}
You are suggesting:
foreach ($foos as $foo) {
if (! is_null($foo) and ! $foo instanceof Face) {
throw new Exception ('AAAGGGGGHHH!');
}
}
How do people feel about that?
On Wed, Jan 15, 2014 at 3:09 PM, Philip Sturgeon pjsturgeon@gmail.comwrote:
Ok, ignoring the int stuff as PHP doesn't generally do that. We don't
want to broach that topic here.As for allowing null, this feature is currently intended as a
syntactic representation of:foreach ($foos as $foo) {
if (! $foo instanceof Face) {
throw new Exception ('AAAGGGGGHHH!');
}
}You are suggesting:
foreach ($foos as $foo) {
if (! is_null($foo) and ! $foo instanceof Face) {
throw new Exception ('AAAGGGGGHHH!');
}
}How do people feel about that?
PHP disallows passing NULL
in a function like:
function foo(MyClass $obj) {}
Unless you explicitly allow it to be null:
function foo(MyClass $obj = null) { }
The first instance will throw an error:
PHP Catchable fatal error: Argument 1 passed to foo() must be an instance
of MyClass, null given
I think this implementation (MyClass[]) should be consistent this when
passing null.
I think this implementation (MyClass[]) should be consistent this when
passing null.
Even without the argument of consistency, the new syntax would be pretty
much useless if NULL
was allowed, since every method would have start
with a call to array_filter
.
Marco Pivetta
-----Original Message-----
From: Marco Pivetta [mailto:ocramius@gmail.com]
Sent: Wednesday, January 15, 2014 9:25 PM
To: Kristopher
Cc: Philip Sturgeon; Robert Stoll; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFCI think this implementation (MyClass[]) should be consistent this when
passing null.Even without the argument of consistency, the new syntax would be pretty
much useless ifNULL
was allowed, since every method would have start
with a call toarray_filter
.Marco Pivetta
You could also think in a different way. NULL
is basically a valid entry in an array. If you apply the restriction as implemented in the pull request then one cannot use the new syntax for arrays which allow NULL, that seems odd to me as well. Especially since class/interface-types are reference types and I regard NULL
as something equal to a null-pointer.
Furthermore, if one does not want to support NULL
in an array currently, then one probably already uses an own collection implementation which already triggers and error, throws an exception respectively, when one tries to add NULL
to the collection.
It seems the pull request does not yet support multidimensional arrays (e.g. Foo[][]) but if we would stick to the restriction now then the consequence should be that this restriction also applies to multi-dimensional arrays. In my opinion, we would spoil valid use cases this way for RFC and for future ones (in the case multi-dimensional arrays will be introduced, other concepts could be affected as well).
Thus I would suggest to remove this check and provide a further SPL data structure implementation instead which does not allow null as entry if this feature is really needed. Seems more appropriate to me than making a restriction in the language itself.
-----Original Message-----
From: Marco Pivetta [mailto:ocramius@gmail.com]
Sent: Wednesday, January 15, 2014 9:25 PM
To: Kristopher
Cc: Philip Sturgeon; Robert Stoll; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFCI think this implementation (MyClass[]) should be consistent this when
passing null.Even without the argument of consistency, the new syntax would be pretty
much useless ifNULL
was allowed, since every method would have start
with a call toarray_filter
.Marco Pivetta
You could also think in a different way.
NULL
is basically a valid entry in an array. If you apply the restriction as implemented in the pull request then one cannot use the new syntax for arrays which allow NULL, that seems odd to me as well. Especially since class/interface-types are reference types and I regardNULL
as something equal to a null-pointer.
Furthermore, if one does not want to supportNULL
in an array currently, then one probably already uses an own collection implementation which already triggers and error, throws an exception respectively, when one tries to addNULL
to the collection.It seems the pull request does not yet support multidimensional arrays (e.g. Foo[][]) but if we would stick to the restriction now then the consequence should be that this restriction also applies to multi-dimensional arrays. In my opinion, we would spoil valid use cases this way for RFC and for future ones (in the case multi-dimensional arrays will be introduced, other concepts could be affected as well).
Thus I would suggest to remove this check and provide a further SPL data structure implementation instead which does not allow null as entry if this feature is really needed. Seems more appropriate to me than making a restriction in the language itself.
I would assume that the majority of people will be using this syntax
to ensure the types of objects.
In English:
"I would like everything in this array to be Foo."
That is much more programatically useful in my opinion than:
"I would like everything in this array to be Foo or maybe null."
If we go with the latter then I still have no idea what is in this
variable, and have to do a whole bunch of checking or
array_filter()
ing, otherwise I am doing this:
$possibleNullValue->getInfo(); // BOOM!
Even if there are use-cases for allowing them I would suggest that
there are probably more use-cases for denying them.
-----Original Message-----
From: Philip Sturgeon [mailto:pjsturgeon@gmail.com]
Sent: Wednesday, January 15, 2014 10:25 PM
To: Robert Stoll
Cc: Marco Pivetta; Kristopher; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFC-----Original Message-----
From: Marco Pivetta [mailto:ocramius@gmail.com]
Sent: Wednesday, January 15, 2014 9:25 PM
To: Kristopher
Cc: Philip Sturgeon; Robert Stoll; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFCI think this implementation (MyClass[]) should be consistent this when
passing null.Even without the argument of consistency, the new syntax would be pretty
much useless ifNULL
was allowed, since every method would have start
with a call toarray_filter
.Marco Pivetta
You could also think in a different way.
NULL
is basically a valid entry in an array. If you apply the restriction
as
implemented in the pull request then one cannot use the new syntax for arrays which allow NULL, that seems odd to me
as
well. Especially since class/interface-types are reference types and I regardNULL
as something equal to a
null-pointer.
Furthermore, if one does not want to supportNULL
in an array currently, then one probably already uses an own
collection implementation which already triggers and error, throws an exception respectively, when one tries to add
NULL
to the collection.It seems the pull request does not yet support multidimensional arrays (e.g. Foo[][]) but if we would stick to the
restriction now then the consequence should be that this restriction also applies to multi-dimensional arrays. In my
opinion,
we would spoil valid use cases this way for RFC and for future ones (in the case multi-dimensional arrays will be
introduced,
other concepts could be affected as well).Thus I would suggest to remove this check and provide a further SPL data structure implementation instead which does
not allow null as entry if this feature is really needed. Seems more appropriate to me than making a restriction in
the
language itself.I would assume that the majority of people will be using this syntax
to ensure the types of objects.In English:
"I would like everything in this array to be Foo."
That is much more programatically useful in my opinion than:
"I would like everything in this array to be Foo or maybe null."
If we go with the latter then I still have no idea what is in this
variable, and have to do a whole bunch of checking or
array_filter()
ing, otherwise I am doing this:$possibleNullValue->getInfo(); // BOOM!
Even if there are use-cases for allowing them I would suggest that
there are probably more use-cases for denying them.--
Fair enough, the example with the English sentence makes pretty much sense from an average user's point of view and thus
most PHP users would probably agree with you (don't take it wrong, I don't imply you are average or something similar).
However, this should not be a decision based on whether many people are preferring it this way or the other way round in
my opinion, since the restriction is going to make it impossible to use it for the use cases where NULL
is a valid
entry.
So, we should ask ourselves, do we really want to exclude a whole bunch of valid use cases or should we decline the
restriction and put more effort in providing alternatives for non-null -containing collections.
See, if we do not introduce the restriction and provide a non-null-containing collection then all use cases can be
supported. That is the way to go IMO.
Or do you have another idea how one can specify that the array can contain null?
And please consider, if you should suggest "function foo(Foo[] $foo=null)" implies that $foo can also contain NULL
then
we have another vague concept in PHP which has a double meaning -> $foo can be NULL
and entries in $foo can be NULL. But
maybe one does not want to allow NULL
for $foo but only for members of $foo.
Hello,
since there is an option for nullable type-hinted variables, it may be
usefull to explicitly allow null values in a type-hinted array too.
e.g.: function foo(Bar[null] = null)
to consider:
- null is not an object
- null is not "nothing"
- null is not "not defined"
- null is not a/any type (even documentation states so)
Java: only reference types are nullable
c#: only if explicitly defined
sql: only if explicitly defined
cryptocompress
e.g.: function foo(Bar[null] = null)
I'd prefer the ? syntax for nullables that C# has. I'm imagining
something like this:
function foo(Bar? $a) {} // $a is Bar/null
function foo(Bar?[] $a) {} // $a is array of Bars/nulls
function foo(Bar[]? $a) {} // $a is array of Bars, or null
function foo(Bar?[]? $a) {} // $a is array of Bars/nulls, or null
--
Andrea Faulds
http://ajf.me/
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Thursday, January 16, 2014 12:54 AM
To: Crypto Compress; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFCe.g.: function foo(Bar[null] = null)
I'd prefer the ? syntax for nullables that C# has. I'm imagining
something like this:function foo(Bar? $a) {} // $a is Bar/null
function foo(Bar?[] $a) {} // $a is array of Bars/nulls
function foo(Bar[]? $a) {} // $a is array of Bars, or null
function foo(Bar?[]? $a) {} // $a is array of Bars/nulls, or null--
Andrea Faulds
http://ajf.me/--
I like Andrea's proposal, this way we can support all scenarios.
It is possible to define that NULL
is a valid entry in an array and we would stick to the same decision as for actual
parameters, namely that one has to define explicitly that null is a valid entry. This would make me happy and I suppose
also Philip.
Just as side notice, this syntax would also give the chance for PHP to get rid of the double meaning of "=null" in a
later version. I am talking about the following case:
function foo(Foo $a=null, $b=1){}
Where one might not want to specify that $a is optional but cannot do it differently at the moment - with the additional
? it could change :)
2014/1/16 Robert Stoll php@tutteli.ch
-----Original Message-----
From: Andrea Faulds [mailto:ajf@ajf.me]
Sent: Thursday, January 16, 2014 12:54 AM
To: Crypto Compress; internals@lists.php.net
Subject: Re: [PHP-DEV] Introducing "Array Of" RFCe.g.: function foo(Bar[null] = null)
I'd prefer the ? syntax for nullables that C# has. I'm imagining
something like this:function foo(Bar? $a) {} // $a is Bar/null
function foo(Bar?[] $a) {} // $a is array of Bars/nulls
function foo(Bar[]? $a) {} // $a is array of Bars, or null
function foo(Bar?[]? $a) {} // $a is array of Bars/nulls, or null--
Andrea Faulds
http://ajf.me/--
I like Andrea's proposal, this way we can support all scenarios.
It is possible to define thatNULL
is a valid entry in an array and we
would stick to the same decision as for actual
parameters, namely that one has to define explicitly that null is a valid
entry. This would make me happy and I suppose
also Philip.Just as side notice, this syntax would also give the chance for PHP to get
rid of the double meaning of "=null" in a
later version. I am talking about the following case:
function foo(Foo $a=null, $b=1){}
Where one might not want to specify that $a is optional but cannot do it
differently at the moment - with the additional
? it could change :)--
- 1 for the RFC
But if i'm not completely wrong, there is performance decrease instead of
increase in your tests?
https://gist.github.com/krakjoe/8444591
[joe@fiji php-src]$ sapi/cli/php isTest.php 10000
objects: 10000
arrayof: 0.00645113
instanceof: 0.00560713
- 1 for the RFC
But if i'm not completely wrong, there is performance decrease instead of
increase in your tests?
https://gist.github.com/krakjoe/8444591[joe@fiji php-src]$ sapi/cli/php isTest.php 10000
objects: 10000
arrayof: 0.00645113
instanceof: 0.00560713
I gave the RFC a few more thoughts and came to the conclusion that it
does not fit to PHP (due to the performance penalties involved).
The syntax merely hide an ugly design. If you would write the same in
normal PHP then probably everyone would agree that it is bad design.
Following an example (doesn't really make sense but outlines the bad design)
function foo(Foo[] $foos){
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}
Is equivalent to
function foo(array $arr){
foreach($arr as $v){
if(!($v instanceof Foo)){
//trigger_error
}
}
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}
The check adds runtime complexity to the function for each call which
is obviously not necessary (once would be good enough). And I doubt
that users would actually make sure that the check is only performed
once and even if you would argue that one should write it as follows:
function bar(Foo[] $foos){
foo($foos);
}
function foo(array $foos){
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}
Then it is still bad design compared to a collection which actually
does the check during the addition of elements.
Although, I like the effort to make PHP somewhat more type safe I am
-1 for this RFC, the implementation respectively. If we want typed
arrays then the array needs to carry the type to be efficient.
Le 16/01/2014 11:01, php@tutteli.ch a écrit :
- 1 for the RFC
But if i'm not completely wrong, there is performance decrease instead of
increase in your tests?
https://gist.github.com/krakjoe/8444591[joe@fiji php-src]$ sapi/cli/php isTest.php 10000
objects: 10000
arrayof: 0.00645113
instanceof: 0.00560713I gave the RFC a few more thoughts and came to the conclusion that it
does not fit to PHP (due to the performance penalties involved).
The performance penalty is the same as if you were type-checking yourself.
And on the gist linked, we can see that the results vary a lot (not
enough iterations probably), it's easy to take only the worst one. Here,
I'll take the one where the numbers are inversed to "prove" my point:
[joe@fiji php-src]$ sapi/cli/php isTest.php 1000
objects: 1000
arrayof: 0.00080991
instanceof: 0.00086308
The syntax merely hide an ugly design. If you would write the same in
normal PHP then probably everyone would agree that it is bad design.
How is type checking a bad design?
Between:
function (array $foos) {
foreach ($foos as $foo) {
if (! $foo instanceof Foo) {
throw new InvalidArgumentException("...");
}
$foo->bar();
}
}
and:
function (array $foos) {
foreach ($foos as $foo) {
$foo->bar(); // BOOM, fatal error if not correct object given
}
}
which one is worse?
It's the same problem than this:
function ($foo) {
$foo->bar(); // fatal error if not correct object given
}
and this:
function (Foo $foo) {
$foo->bar();
}
Following an example (doesn't really make sense but outlines the bad
design)function foo(Foo[] $foos){
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}Is equivalent to
function foo(array $arr){
foreach($arr as $v){
if(!($v instanceof Foo)){
//trigger_error
}
}
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}The check adds runtime complexity to the function for each call which is
obviously not necessary (once would be good enough). And I doubt that
users would actually make sure that the check is only performed once and
even if you would argue that one should write it as follows:function bar(Foo[] $foos){
foo($foos);
}
function foo(array $foos){
if(count($foos) > 0){
$a = array_pop($foos);
//do something
foo($foos);
}
}Then it is still bad design compared to a collection which actually does
the check during the addition of elements.
Although, I like the effort to make PHP somewhat more type safe I am -1
for this RFC, the implementation respectively. If we want typed arrays
then the array needs to carry the type to be efficient.
Matthieu
Hi all,
On Thu, Jan 16, 2014 at 7:49 PM, Matthieu Napoli matthieu@mnapoli.frwrote:
The syntax merely hide an ugly design. If you would write the same in
normal PHP then probably everyone would agree that it is bad design.
How is type checking a bad design?
Type checking is not bad.
Alternatively, DbC (design by contract) may be useful.
Cleaner and could be faster.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
The performance penalty is the same as if you were type-checking yourself.
(Sorry if I'm stepping on your toes here Joe, since it was you who
pointed this out to me):
This is not completely true. With arrayof, there are two iterations of
the passed value - one in C and one in PHP, vs only one iteration in
the foreach/instanceof approach.
However:
- as you point out, the performance penalty for the check is
negligible if it even exists - if you don't use the syntax there is no penalty whatsoever
so for me this is a complete non-issue. The concise syntax and strong
semantic possibilities this brings far outweigh a few microseconds of
slowdown.
Thanks, Chris
2014/1/16 Matthieu Napoli matthieu@mnapoli.fr
Le 16/01/2014 11:01, php@tutteli.ch a écrit :
- 1 for the RFC
But if i'm not completely wrong, there is performance decrease instead of
increase in your tests?
https://gist.github.com/krakjoe/8444591[joe@fiji php-src]$ sapi/cli/php isTest.php 10000
objects: 10000
arrayof: 0.00645113
instanceof: 0.00560713I gave the RFC a few more thoughts and came to the conclusion that it
does not fit to PHP (due to the performance penalties involved).The performance penalty is the same as if you were type-checking yourself.
And on the gist linked, we can see that the results vary a lot (not enough
iterations probably), it's easy to take only the worst one. Here, I'll take
the one where the numbers are inversed to "prove" my point:[joe@fiji php-src]$ sapi/cli/php isTest.php 1000
objects: 1000
arrayof: 0.00080991
instanceof: 0.00086308
Yes i saw the good result too. Just wondered why native PHP was slower
sometimes...
How is type checking a bad design?
Between:
function (array $foos) {
foreach ($foos as $foo) {
if (! $foo instanceof Foo) {
throw new InvalidArgumentException("...");
}
$foo->bar();
}
}and:
function (array $foos) {
foreach ($foos as $foo) {
$foo->bar(); // BOOM, fatal error if not correct object given
}
}which one is worse?
You got me wrong, I don't think that type checking as such is bad but type checking in the way the RFC promotes it is bad design IMO. If I expect an array with members of a certain type (regardless if including null or not) then I would not write any of the above code because this is exactly the bad design I was writing about.
Wouldn't you agree with me that it would be better to type check the entries when they are added rather than during each function call?
Imagine function foo(Foo[] $foos){} which calls bar and baz which in turn call several other functions which all have the same type hint Foo[].
The result would be that you have increased your runtime complexity by the factor of function calls. That's really ugly and I don't think that the language itself should promote such bad design. If you go further and support multi-dimensional arrays the same way then you would add a complexity of n*m for each function call with such a type hint.
However, I like the basic idea of the RFC, namely typed arrays. I think a better implementation would be to introduce that an array holds (visible only internally - could be exposed to userland later) the defined type and performs the necessary checks during addition and therefore the runtime complexity for the type hint checks would no longer be linear but constant. Yet, it is probably better to introduce another internal data structure for this purpose in order that the type hint "array" does not suffer from the additional checks.
An alternative approach, without changing the language, would be to provide an additional SPL data structure instead which performs the type check during the addition of an entry.
Nevertheless, the implementation of the RFC as such is not useless. We could introduce a function is_arrayOf(array $arr, $type, $nullable=false) which could perform the check as implemented in the pull request (including the nullable option). And I suppose you can come up with valid uses cases where such a check makes actually sense and worth the new function.
How is type checking a bad design?
Between:
function (array $foos) {
foreach ($foos as $foo) {
if (! $foo instanceof Foo) {
throw new InvalidArgumentException("...");
}
$foo->bar();
}
}and:
function (array $foos) {
foreach ($foos as $foo) {
$foo->bar(); // BOOM, fatal error if not correct object given
}
}which one is worse?
You got me wrong, I don't think that type checking as such is bad but type checking in the way the RFC promotes it is bad design IMO. If I expect an array with members of a certain type (regardless if including null or not) then I would not write any of the above code because this is exactly the bad design I was writing about.
Wouldn't you agree with me that it would be better to type check the entries when they are added rather than during each function call?
Imagine function foo(Foo[] $foos){} which calls bar and baz which in turn call several other functions which all have the same type hint Foo[].
The result would be that you have increased your runtime complexity by the factor of function calls. That's really ugly and I don't think that the language itself should promote such bad design. If you go further and support multi-dimensional arrays the same way then you would add a complexity of n*m for each function call with such a type hint.
I'm absolutely +1 with such a statement.
However, I like the basic idea of the RFC, namely typed arrays. I think a better implementation would be to introduce that an array holds (visible only internally - could be exposed to userland later) the defined type and performs the necessary checks during addition and therefore the runtime complexity for the type hint checks would no longer be linear but constant. Yet, it is probably better to introduce another internal data structure for this purpose in order that the type hint "array" does not suffer from the additional checks.
An alternative approach, without changing the language, would be to provide an additional SPL data structure instead which performs the type check during the addition of an entry.
Yes, yes and yes again. +1
This RFC shows that we lack "array of" as a whole structure in PHP,
like Java has Vectors. We already talked about this in the past.
I'm in favor of designing a new "typed array" structure , instead of
adding a new syntax that checks things at runtime of every function
call, mainly by iterating over the array at runtime.
I dont think we can accept such a penalty, particulary in the case of
nested function calls with the same signature, all requiring the
engine to iterate for type checking.
Julien.P
I'm in favor of designing a new "typed array" structure , instead of
adding a new syntax that checks things at runtime of every function
call, mainly by iterating over the array at runtime.
This, while useful, doesn't solve the same problem as this RFC is solving.
You wouldn't be able to type hint for the type contained within the
structure without some form of new syntax.
What if we did both? So that the new syntax actually expects an
SplTypedArray (or whatever you want to call it) and if an instance of this
structure is passed the class entry attached to the structure can be used
as an O(1) shortcut, but if an array is passed it is run through
SplTypedArray::fromArray(), allowing users to pass an array and take the
performance hit if they want to.
Thanks, Chris
Hi,
Am Mittwoch, 15. Januar 2014 um 23:00 schrieb Robert Stoll:
Fair enough, the example with the English sentence makes pretty much sense from an average user's point of view and thus
most PHP users would probably agree with you (don't take it wrong, I don't imply you are average or something similar).
However, this should not be a decision based on whether many people are preferring it this way or the other way round in
my opinion, since the restriction is going to make it impossible to use it for the use cases whereNULL
is a valid
entry.
So, we should ask ourselves, do we really want to exclude a whole bunch of valid use cases or should we decline the
restriction and put more effort in providing alternatives for non-null -containing collections.See, if we do not introduce the restriction and provide a non-null-containing collection then all use cases can be
supported. That is the way to go IMO.
Or do you have another idea how one can specify that the array can contain null?
And please consider, if you should suggest "function foo(Foo[] $foo=null)" implies that $foo can also containNULL
then
we have another vague concept in PHP which has a double meaning -> $foo can beNULL
and entries in $foo can be NULL. But
maybe one does not want to allowNULL
for $foo but only for members of $foo.
if you pass an array which mixes both objects and null and you want to work on the objects, you still have to do the checks yourself:
function f (A[] $list)
{
foreach ($list as $entry)
{
if (!is_null($entry))
{
$entry->doSth();
}
}
}
But in this case you could just omit the type hint and check it internally:
function f ($list)
{
foreach ($list as $entry)
{
if (!is_null($entry) && ($entry instanceof A))
{
$entry->doSth();
}
}
}
The thought of this proposal is that the complete checking is done with just the type hint.
And allowing null would make this obsolete.
Also, you would then have the duplicated runtime impact:
you need to check the array twice:
- check for null & A (type hint)
- check for A
instead of just one.
Cheers
Jannik
if you pass an array which mixes both objects and null and you want to work on the objects, you still have to do the checks
yourself:
I agree, in this case it would be useful if Foo[] excludes members which are NULL. I guess I did not make it clear enough what I tried to point out.
A new feature should not just work for some use cases because the majority of people would use it this way but also for other use cases as long as they are valid.
So my point was that the RFC has to consider both cases, once excluding NULL
and once with NULL
as valid entry. As long as it doesn't it is incomplete IMO.
Andrea made a nice suggestion for the syntax and I would go for it:
function foo(Bar? $a) {} // $a is Bar/null
function foo(Bar?[] $a) {} // $a is array of Bars/nulls
function foo(Bar[]? $a) {} // $a is array of Bars, or null
function foo(Bar?[]? $a) {} // $a is array of Bars/nulls, or null
Hi Marco, everyone,
[...]
Even without the argument of consistency, the new syntax would be pretty
much useless ifNULL
was allowed, since every method would have start
with a call toarray_filter
.
Very much true. Allowing null would introduce a huge hole for null pointer errors.
cu,
Lars
2014/1/15 Philip Sturgeon pjsturgeon@gmail.com
Hey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
Hello,
this is a nice proposal.
I hope that it is not limited to arrays only... All tranversables should be
acceptable (as they are acceptable for variadiac functions). Otherwise this
will lead to unnecessary (and costly) convertions.
Lazare INEPOLOGLOU
Ingénieur Logiciel
I hope that it is not limited to arrays only... All tranversables
should be acceptable (as they are acceptable for variadiac functions).
Otherwise this will lead to unnecessary (and costly) convertions.
those can't be checked.
johannes
On Wed, Jan 15, 2014 at 8:49 PM, Lazare Inepologlou linepogl@gmail.comwrote:
2014/1/15 Philip Sturgeon pjsturgeon@gmail.com
Hey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.Hello,
this is a nice proposal.
I hope that it is not limited to arrays only... All tranversables should be
acceptable (as they are acceptable for variadiac functions). Otherwise this
will lead to unnecessary (and costly) convertions.
An array is not just traversable - it is also array accessible and
countable, as well as passable-to-array-functions. Allowing to pass
Traversables to an array typehint violates the type constraint.
Nikita
2014/1/15 Philip Sturgeon pjsturgeon@gmail.com
Hey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.Hello,
this is a nice proposal.
I hope that it is not limited to arrays only... All tranversables should be
acceptable (as they are acceptable for variadiac functions). Otherwise this
will lead to unnecessary (and costly) convertions.Lazare INEPOLOGLOU
Ingénieur Logiciel
Currently function (array Foo) is ONLY arrays, not number of
interfaces will change that.
This RFC keeps to the same logic, but a later RFC could (and IMO
absolutely should) address this. I would suggest that this is a
different issue, and should be kept separate.
Hi Philip,
[...]
It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
Very nice proposal. One thing I noticed by reading the code (and the tests9 is that it bails out at the first offender. Given I hint for Foo[], and pass [new Foo(), new Bar(), new Baz()] it will only inform me about Bar violating Foo. I would like to have a more descriptive error message that contains both Bar and Baz.
cu,
Lars
Hi Philip,
[...]
It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.Very nice proposal. One thing I noticed by reading the code (and the
tests9 is that it bails out at the first offender. Given I hint for
Foo[], and pass [new Foo(), new Bar(), new Baz()] it will only inform me
about Bar violating Foo.
So will calling foo(""); where foo's definition is foo(Asd $asd, Qwe $qwe);
I, for one, don't see a problem here.
Given I hint for Foo[], and pass [new Foo(), new Bar(), new Baz()] it will
only inform me about Bar violating Foo. I would like to have a more descriptive
error message that contains both Bar and Baz.
While I see where you're coming from with this, it's non-trial to
implement this in a sane way, both in code and to handle every
possible scenario in a logical way. Suppose I pass an array or 10000
objects which instances of 10000 different classes which do not
satisfy the type hint? I guess you'd want to do something like
<= 3 offenders - give their class names and indices
3 offenders - give an error along the lines "passed array elements are completely wrong" (or maybe report first three and append a "and other errors")
...but IMO the complexity this would add is not worth the effort. From
a consistency point of view it should just use the same error logic as
the shiny new variadics feature - which also bails out at the first
offender.
Thanks, Chris
Philip Sturgeon wrote:
Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
I'm quite happy to put my hands up and say that despite having been programming
since the early 70's some of these 'essential facilities' are simply going over
my head. I've programmed with 'strict' languages and had to work around their
restrictions in the past, so the 'loose' format of PHP used to be a pleasure. So
all of these 'improvements' to keep to nibble away at the that freedom is a
pain. My IDE provides all of the 'type-hinting' that I need and a lot more
besides, totally outside the final code base. Many of the e_strict rules cause
problems resulting in a lot of duplication of code, adding facilities which
create more hinting/type checks still seems backwards.
This may just be my misunderstanding the OO basis people are working on, and
many of my 'objects' are persisted directly in the database, so the array of
elements is simply a record from the database. That record may have a type field
so that the resulting array is a mixture of types of object, but all of the same
base class. As with other additions made, I don't understand where this
'improved type-hinting' fits into the general development of PHP? How much code
will actually benefit from this addition, and how much will simply ignore it?
--
Lester Caine - G8HFL
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk
I'm going to fowl up this conversation by describing what HHVM's Hack
syntax does for this. Partly to encourage PHP to do the same, partly
to just lay out the edge cases we thought about on the way to
developing the syntax we landed with.
-
Generics Syntax - Allows creation of typed classes which repeat
common functionality with specific implementations
class Foo<T> {
protected T $foo;public function getFoo(): T {
return $this->foo;
}pubilc function setFoo(T $foo) {
$this->foo = $foo;
}
}
$f = new Foo<Bar>();
$f->setFoo(new Bar());
$b = $f->getFoo();
- Typed arrays - Arrays are a special primitive which can be typed as
implicitly or explicitly numerically indexed, or associative, and to
specific types:
array<Tv> or array<Tk,Tv>
function foo(array<Bar> $numIdxArrayOfBar, array<int,Baz>
$numIdxArrayOfBaz, array<string,$Bong> $assocArrayOfBong) { ... }
Since the value type is unconstrained, it can be a generic type as
well, so a numerically indexed array of associative arrays of strings
would look like array<array<string,string>> and so on.
-
Nullable types - Any type preceeded by a question mark may be that
type or null:
function foo(?Bar $barOrNull, Baz $bar, ?Blong $blongOrNull) {...} -
Soft types - Any type preceeded by an at sign is hinted as that
type, but not checked:
function foo(@Bar $IHopeYoureABarObject) {...}
Within the scope of this RFC, I want to encourage
array<Tv>/array<Tk,Tv> syntax (with nullable/soft modifiers) as I
think they cover every edge case presented by this discussion so far.
It also covers elements not handled by the proposed syntax (index
types). The syntax will be familiar to developers coming from C++ and
it leaves room to entertain generics in general.
-Sara
Hey Sara,
- Typed arrays - Arrays are a special primitive which can be typed as
implicitly or explicitly numerically indexed, or associative, and to
specific types:
array<Tv> or array<Tk,Tv>
Out of curiosity, does HHVM support both use cases: NULL
as a valid member and NULL
as an error?
If so, how does the syntax differ?
- Typed arrays - Arrays are a special primitive which can be typed as
implicitly or explicitly numerically indexed, or associative, and to
specific types:
array<Tv> or array<Tk,Tv>Out of curiosity, does HHVM support both use cases:
NULL
as a valid member andNULL
as an error?
If so, how does the syntax differ?
That's captured via Nullable types.
array<Foo> is an array of Foo objects (nulls not allowed).
array<?Foo> is an array of (Foo Objects or NULL)
-Sara
Hi all,
I'm going to fowl up this conversation by describing what HHVM's Hack
syntax does for this. Partly to encourage PHP to do the same, partly
to just lay out the edge cases we thought about on the way to
developing the syntax we landed with.
Generics Syntax - Allows creation of typed classes which repeat
common functionality with specific implementations
class Foo<T> {
protected T $foo;public function getFoo(): T {
return $this->foo;
}pubilc function setFoo(T $foo) {
$this->foo = $foo;
}
}$f = new Foo<Bar>();
$f->setFoo(new Bar());
$b = $f->getFoo();
- Typed arrays - Arrays are a special primitive which can be typed as
implicitly or explicitly numerically indexed, or associative, and to
specific types:
array<Tv> or array<Tk,Tv>function foo(array<Bar> $numIdxArrayOfBar, array<int,Baz>
$numIdxArrayOfBaz, array<string,$Bong> $assocArrayOfBong) { ... }Since the value type is unconstrained, it can be a generic type as
well, so a numerically indexed array of associative arrays of strings
would look like array<array<string,string>> and so on.
Nullable types - Any type preceeded by a question mark may be that
type or null:
function foo(?Bar $barOrNull, Baz $bar, ?Blong $blongOrNull) {...}Soft types - Any type preceeded by an at sign is hinted as that
type, but not checked:
function foo(@Bar $IHopeYoureABarObject) {...}
Within the scope of this RFC, I want to encourage
array<Tv>/array<Tk,Tv> syntax (with nullable/soft modifiers) as I
think they cover every edge case presented by this discussion so far.
It also covers elements not handled by the proposed syntax (index
types). The syntax will be familiar to developers coming from C++ and
it leaves room to entertain generics in general.
I prefer generics syntax.
It's rather common syntax and has more abilities.
It's better to have common syntax with HHVM, too.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
I'm going to fowl up this conversation by describing what HHVM's Hack
syntax does for this. Partly to encourage PHP to do the same, partly
to just lay out the edge cases we thought about on the way to
developing the syntax we landed with.
Generics Syntax - Allows creation of typed classes which repeat
common functionality with specific implementations
class Foo<T> {
protected T $foo;public function getFoo(): T {
return $this->foo;
}pubilc function setFoo(T $foo) {
$this->foo = $foo;
}
}$f = new Foo<Bar>();
$f->setFoo(new Bar());
$b = $f->getFoo();
- Typed arrays - Arrays are a special primitive which can be typed as
implicitly or explicitly numerically indexed, or associative, and to
specific types:
array<Tv> or array<Tk,Tv>function foo(array<Bar> $numIdxArrayOfBar, array<int,Baz>
$numIdxArrayOfBaz, array<string,$Bong> $assocArrayOfBong) { ... }Since the value type is unconstrained, it can be a generic type as
well, so a numerically indexed array of associative arrays of strings
would look like array<array<string,string>> and so on.
Nullable types - Any type preceeded by a question mark may be that
type or null:
function foo(?Bar $barOrNull, Baz $bar, ?Blong $blongOrNull) {...}Soft types - Any type preceeded by an at sign is hinted as that
type, but not checked:
function foo(@Bar $IHopeYoureABarObject) {...}
Within the scope of this RFC, I want to encourage
array<Tv>/array<Tk,Tv> syntax (with nullable/soft modifiers) as I
think they cover every edge case presented by this discussion so far.
It also covers elements not handled by the proposed syntax (index
types). The syntax will be familiar to developers coming from C++ and
it leaves room to entertain generics in general.-Sara
After a little thought, I think I'd rather we use the HHVM syntax here.
Having "Array" for an untyped array but "Bar[]" for a typed one is
silly. "Array" and "Array<Bar>" make more sense. Being able to type keys
would be nice, too.
However, I have but one little issue with the HHVM syntax. Why is the ?
before the type name? I much prefer the C#-style Bar? to this confusing
?Bar. I suppose this is only a minor issue, though.
--
Andrea Faulds
http://ajf.me/
However, I have but one little issue with the HHVM syntax. Why is the ?
before the type name? I much prefer the C#-style Bar? to this confusing
?Bar. I suppose this is only a minor issue, though.
Two reasons come to mind, both essentially aesthetic:
-
Symbol crowding: function foo(array? &$bar) { }
bar by ref expects array, but may take null (which is perfectly common
for a by-ref variable). Trouble is, '? &$' is starting to look
perlish. -
Generic expansion:
Prefix: function foo(?array<Bar<?int>> $baz)...
Suffix: function foo(array<Bar<int?>>? $bar)...
Both proclaim a nullable array of non-nullable Bar objects of nullable
type int. The prefix version makes it much more obvious which '?'
goes with which portion of the type structure.
function foo(array?<Bar<int?>> $baz)... sounds tempting, but some
shift/reduce conflicts start to emerge out of that stacking of tokens.
Resolvable, of course, but complicating the parser rules over a bit
of aesthetics like that.... You can't see it, but I've got my frownie
face on right now.
-Sara
P.S. - I'm not voting for or against anything at this point either.
Just offering input during discussion phase, as we're all meant to. :)
However, I have but one little issue with the HHVM syntax. Why is the ?
before the type name? I much prefer the C#-style Bar? to this confusing
?Bar. I suppose this is only a minor issue, though.Two reasons come to mind, both essentially aesthetic:
Symbol crowding: function foo(array? &$bar) { }
bar by ref expects array, but may take null (which is perfectly common
for a by-ref variable). Trouble is, '? &$' is starting to look
perlish.Generic expansion:
Prefix: function foo(?array<Bar<?int>> $baz)...
Suffix: function foo(array<Bar<int?>>? $bar)...Both proclaim a nullable array of non-nullable Bar objects of nullable
type int. The prefix version makes it much more obvious which '?'
goes with which portion of the type structure.function foo(array?<Bar<int?>> $baz)... sounds tempting, but some
shift/reduce conflicts start to emerge out of that stacking of tokens.
Resolvable, of course, but complicating the parser rules over a bit
of aesthetics like that.... You can't see it, but I've got my frownie
face on right now.-Sara
P.S. - I'm not voting for or against anything at this point either.
Just offering input during discussion phase, as we're all meant to. :)
Sara,
In the original internals thread about generics, you mention that the
HHVM team were going to donate their effort and patch to PHP so we could
have generics in PHP .... so ... how did that work out, is there a patch
(even a half finished one) ??
I'm a bit disappointed that this has been turned into a conversation
about something I see as completely different.
I wasn't looking to introduce a paradigm, and think it would be quite
terrible to use the syntax for generics for this; I only want to hint
for generics when I can program with generics, and even if I wrote the
patch next week, the original conversation made it seem like it would
never be merged anyway ...
Was there some technical difficulty that stopped the work on generics
when it was first brought up, or did you just realise that it would
never get through ??
Original conversation about generics:
Cheers
Joe
Was there some technical difficulty that stopped the work on
generics when it was first brought up, or did you just realize that it would
never get through ??
A little from column A, a little from column B.
None of the technical challenges were insurmountable, but the
temperature for Generics felt tepid at the time (not nearly a 2/3
majority), so it was back-burnered for more productive stuff. Reckon
the mood has changed in the past year or so?
-Sara
Was there some technical difficulty that stopped the work on
generics when it was first brought up, or did you just realize that it would
never get through ??A little from column A, a little from column B.
None of the technical challenges were insurmountable, but the
temperature for Generics felt tepid at the time (not nearly a 2/3
majority), so it was back-burnered for more productive stuff. Reckon
the mood has changed in the past year or so?-Sara
I'm not really sure that it has, and if it has, it's only because people
view it as an overhead free way of achieving what we set out to achieve
here, even though its not really, the actual type hint would be ... I
digress ... I don't really think anyone is thinking it through ...
When you think about it, we couldn't just introduce generics right now,
we have an incomplete type hinting system and it's terribly inconsistent
for new HashMap<int, string>() to be valid but not have the ability to
hint for int or string elsewhere.
It could be done, but it seems ... horrible ... I really think scalar
hints have to be supported before generics, and there are so many
patches for that and even more opinions, I'm not even sure we are
capable of coming to the right decision, we haven't yet, the correct
patch for scalar hinting exists, has done for a while ...
To a lesser extent, you would want return type hints too, if nothing
other than to give the compiler every opportunity to detect
inconsistency in the actual use of generics before we get as far as
execution.
That said, I'd love it, quite happily will put time into working on any
of the things I mentioned, but I have literally no idea how to change
minds ...
Any, or all of the things I just said are not small changes, aimed at
introducing completely alien concepts, alien both to the language and
the people using PHP ... a completely new programming paradigm, that's
really not what we were going for at all here, a simple type hint was all.
I know you know all of what I just said, but for those reading ..
Cheers
Joe
Hi!
After a little thought, I think I'd rather we use the HHVM syntax here.
Having "Array" for an untyped array but "Bar[]" for a typed one is
silly. "Array" and "Array<Bar>" make more sense. Being able to type keys
would be nice, too.
Except that there's no type "array<Bar>" in PHP, so we're just inventing
things out of the thin air that mean nothing. Just because some other
language has common syntax - which in that language means something,
since they actually have typed arrays. But in PHP it doesn't mean
anything except being pulled in to save couple of lines of code. I think
we should not do such things in PHP - if we want to have language that
makes sense and not just a hodgepodge of random syntax constructs pulled
from all over the place and hastily bolted on together - we should not
put in any syntaxes that do not make sense in the rest of the language.
--
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227
Hi Phil,
On Thu, Jan 16, 2014 at 2:17 AM, Philip Sturgeon pjsturgeon@gmail.comwrote:
Hey,
This is my first RFC so give me a little leeway if I get things wrong.
https://wiki.php.net/rfc/arrayof
The implementation has been written by Joe Watkins, and I will be
handling the RFC process for him.It is aimed at PHP 5.6, and so far the release managers seem to be ok
with the idea of this potentially being merged after the alpha
release, so this should not be considered an issue.Everything is open for discussion, especially the current error
messages. They are not perfect, so let us know if you have better
ideas.
First of all, congrats on getting your first RFC out; despite the issues
brought up so far, the idea itself is certainly interesting :)
I was curious about whether it would be possible to perform this type check
outside of the function context as well? For example:
if ($array instanceof Foo[]) { ... }
From what I could tell, this is not part of the RFC.
As an aside, for the fun of it, I thought of this arcane casting syntax:
$arr = (int[])$arr;
--
--
Tjerk