Hello,
I wanted to garnish feedback on a RFC proposal. This is just a concept at
this point, and is inspired by the null coalesce operator.
Code will error if a non-array value is passed through a looping feature.
For example, this code:
<?php
$foo = "abc";
foreach ($foo as $bar) {
echo $bar;
}
will result in the error:
PHP Warning: Invalid argument supplied for foreach() in test.php on line 3
To prevent this, the logical solution is to wrap this in an is_array check:
<?php
$foo = "abc";
if (is_array($foo)) {
foreach ($foo as $bar) {
echo $bar;
}
}
This code runs successfully and does not error out. For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead of
wrapping the block within an is_array check:
<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Let me know your thoughts.
Cheers,
Mark
The idea is good, but I don't know if it is more clear than an 'if()'
Em 11 de jul de 2017 12:15 PM, "Mark Shust" mark@shust.com escreveu:
Hello,
I wanted to garnish feedback on a RFC proposal. This is just a concept at
this point, and is inspired by the null coalesce operator.Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
echo $bar;
}
will result in the error:
PHP Warning: Invalid argument supplied for foreach() in test.php on line 3
To prevent this, the logical solution is to wrap this in an is_array check:
<?php
$foo = "abc";
if (is_array($foo)) {
foreach ($foo as $bar) {
echo $bar;
}
}
This code runs successfully and does not error out. For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Let me know your thoughts.
Cheers,
Mark
"David Rodrigues" wrote in message
news:CAEsg9X2ECG62i7Z_Nu11kqr7yVBkmUcd3MxGt78ULAmpFx--_w@mail.gmail.com...
The idea is good, but I don't know if it is more clear than an 'if()'
I think that this proposal is totally ridiculous and should be shot down in
flames. My reasoning is as follows:
-
There should be a rule that anything which can be achieved with 5 lines
or less in userland code should be automatically excluded from becoming a
change to the language. The cost of changing the language in order to get
around the laziness of a small number of users versus the "benefit" of
making the language more complicated for the rest of us, as well as adding
to the maintenance burden is simply not worth it. -
Proposals such as this violate the first rule of good programming which
is to provide code which is readable and therefore understandable by others,
and therefore maintainable. I don't know about you, but I find it much
easier to read words than symbols. The idea that the code "if
(is_array($foo))" is too verbose and should be replaced with a shorthand
symbol is just too ridiculous for word. If any more of these shortcuts is
implemented then I'm afraid that code will look too much like a bunch of
hieroglyphics and become far less readable.
Just my 2 cents worth.
--
Tony Marston
Em 11 de jul de 2017 12:15 PM, "Mark Shust" mark@shust.com escreveu:
Hello,
I wanted to garnish feedback on a RFC proposal. This is just a concept at
this point, and is inspired by the null coalesce operator.Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
echo $bar;
}
will result in the error:
PHP Warning: Invalid argument supplied for foreach() in test.php on line
3To prevent this, the logical solution is to wrap this in an is_array
check:<?php
$foo = "abc";
if (is_array($foo)) {
foreach ($foo as $bar) {
echo $bar;
}
}
This code runs successfully and does not error out. For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Let me know your thoughts.
Cheers,
Mark
On Thu, Jul 13, 2017 at 2:55 AM, Tony Marston TonyMarston@hotmail.com
wrote:
"David Rodrigues" wrote in message news:CAEsg9X2ECG62i7Z_Nu11kqr7
yVBkmUcd3MxGt78ULAmpFx--_w@mail.gmail.com...The idea is good, but I don't know if it is more clear than an 'if()'
I think that this proposal is totally ridiculous and should be shot down
in flames. My reasoning is as follows:
There should be a rule that anything which can be achieved with 5 lines
or less in userland code should be automatically excluded from becoming a
change to the language. The cost of changing the language in order to get
around the laziness of a small number of users versus the "benefit" of
making the language more complicated for the rest of us, as well as adding
to the maintenance burden is simply not worth it.Proposals such as this violate the first rule of good programming which
is to provide code which is readable and therefore understandable by
others, and therefore maintainable. I don't know about you, but I find it
much easier to read words than symbols. The idea that the code "if
(is_array($foo))" is too verbose and should be replaced with a shorthand
symbol is just too ridiculous for word. If any more of these shortcuts is
implemented then I'm afraid that code will look too much like a bunch of
hieroglyphics and become far less readable.Just my 2 cents worth.
--
Tony MarstonEm 11 de jul de 2017 12:15 PM, "Mark Shust" mark@shust.com escreveu:
Hello,
I wanted to garnish feedback on a RFC proposal. This is just a concept at
this point, and is inspired by the null coalesce operator.Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
echo $bar;
}
will result in the error:
PHP Warning: Invalid argument supplied for foreach() in test.php on
line 3To prevent this, the logical solution is to wrap this in an is_array
check:<?php
$foo = "abc";
if (is_array($foo)) {
foreach ($foo as $bar) {
echo $bar;
}
}
This code runs successfully and does not error out. For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Let me know your thoughts.
Cheers,
Mark--
The more I think about this, the more I think that the throwing a warning
when the variable is not an array is the proper thing to do. The cost in
missed mistakes is much larger than the tiny savings in code that some
people would get.
Walter
The greatest dangers to liberty lurk in insidious encroachment by men of
zeal, well-meaning but without understanding. -- Justice Louis D. Brandeis
Hello :-),
Thank you for the proposal. I have a question though: How is it
different from:
-
foreach ($foo ?: [] as $bar) { … }
if$foo
does not exist, -
foreach ((array) $foo as $bar) { … }
if$foo
is not an array.
I understand your issue, but you can probably type your data with
iterable
, Generator
, array
, Iterator
…
Also, I am not sure that ??$x
really means if (is_array($x)) { … }
.
Regards.
Hello,
I wanted to garnish feedback on a RFC proposal. This is just a concept at
this point, and is inspired by the null coalesce operator.Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
echo $bar;
}
will result in the error:
PHP Warning: Invalid argument supplied for foreach() in test.php on line 3
To prevent this, the logical solution is to wrap this in an is_array check:
<?php
$foo = "abc";
if (is_array($foo)) {
foreach ($foo as $bar) {
echo $bar;
}
}
This code runs successfully and does not error out. For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Let me know your thoughts.
Cheers,
Mark
PHP already exhibits the skipping behaviour (it only emits a warning
for the wrong type used inforeach
, skips the loop, and then
continues with remaining code).
Yes, a warning is not an error. If someone dont care about warnings from
error prone code, set the error_reporting accordingly to hide the messages.
With the following code you do not even get a warning about a undefined
variable.
foreach($foobar ?? [] as $value) {
var_dump($value);
}
For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the syntax you suggest doesn't read quite right. As has been pointed out, this differs from existing features in two ways:
- the special handling is for any non-iterable value, not just null or empty/falsey values, for which you could use $foo??[] and $foo?:[] respectively
- the handling is to skip the loop, not loop once assigning $bar to the scalar value, as would happen with (array)$foo
The challenge, then, is to come up with some syntax that somehow suggests these rules. The "??" is too much like the null coalesce, which would be misleading.
The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire someone else.
Regards,
--
Rowan Collins
[IMSoP]
Thanks for the great feedback.
Based on the last mindset on keyword syntax, this comes to mind, intended
to be used similarly to the 'use' keyword when used within the context of a
closure:
foreach ($foo as $bar) if (is_array) {
...
}
I don't think this is a vast improvement over wrapping this within an
is_array check, however it does avoid the additional nest/wrapping. I was
hoping for something that reads a bit more concisely or with a bit more
syntactical sugar than the above. I think this does read nicely though.
Cheers,
Mark
On Tue, Jul 11, 2017 at 1:50 PM Rowan Collins rowan.collins@gmail.com
wrote:
For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the syntax
you suggest doesn't read quite right. As has been pointed out, this differs
from existing features in two ways:
- the special handling is for any non-iterable value, not just null or
empty/falsey values, for which you could use $foo??[] and $foo?:[]
respectively- the handling is to skip the loop, not loop once assigning $bar to the
scalar value, as would happen with (array)$fooThe challenge, then, is to come up with some syntax that somehow suggests
these rules. The "??" is too much like the null coalesce, which would be
misleading.The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire
someone else.Regards,
--
Rowan Collins
[IMSoP]
If you were willing to accept
foreach ($foo as $bar) if (is_array) {
...
}
as a solution, then you might as well use
if (is_array($foo)) foreach ($foo as $bar) {
...
}
I wonder if this could be better achieved by expanding what the error
suppression operator @
can do? This entire behaviour seems more like an
error suppression action on foreach
to me, otherwise should we consider
coalescing operators for other types/creating a more generic one?
Going back to the error suppression operator:
e.g. perhaps
foreach ($foo @as $bar) {
...
}
could prevent skip past execution of the entire foreach block if there is
an error using $foo as an array. So might make most sense to place the @
on as
, IMO, but I guess arguments could be made to place it like
@foreach ($foo as $bar)
or foreach @($foo as $bar)
.
Regards,
Aidan
Thanks for the great feedback.
Based on the last mindset on keyword syntax, this comes to mind, intended
to be used similarly to the 'use' keyword when used within the context of a
closure:foreach ($foo as $bar) if (is_array) {
...
}I don't think this is a vast improvement over wrapping this within an
is_array check, however it does avoid the additional nest/wrapping. I was
hoping for something that reads a bit more concisely or with a bit more
syntactical sugar than the above. I think this does read nicely though.Cheers,
MarkOn Tue, Jul 11, 2017 at 1:50 PM Rowan Collins rowan.collins@gmail.com
wrote:For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the syntax
you suggest doesn't read quite right. As has been pointed out, this
differs
from existing features in two ways:
- the special handling is for any non-iterable value, not just null or
empty/falsey values, for which you could use $foo??[] and $foo?:[]
respectively- the handling is to skip the loop, not loop once assigning $bar to the
scalar value, as would happen with (array)$fooThe challenge, then, is to come up with some syntax that somehow suggests
these rules. The "??" is too much like the null coalesce, which would be
misleading.The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire
someone else.Regards,
--
Rowan Collins
[IMSoP]
Aidan,
Fantastic suggestion (@as) -- that is really the succinctness I was
initially looking for, and I think the intention makes a lot of sense. My
only concern/issue would be to make sure that isn't considered a
'suppressor' -- but it's actual intent is to skip the execution of the
foreach to prevent the error/loop from occurring (rather than just
suppressing an error).
Cheers,
Mark
If you were willing to accept
foreach ($foo as $bar) if (is_array) { ... }
as a solution, then you might as well use
if (is_array($foo)) foreach ($foo as $bar) { ... }
I wonder if this could be better achieved by expanding what the error
suppression operator@
can do? This entire behaviour seems more like an
error suppression action onforeach
to me, otherwise should we consider
coalescing operators for other types/creating a more generic one?Going back to the error suppression operator:
e.g. perhaps
foreach ($foo @as $bar) { ... }
could prevent skip past execution of the entire foreach block if there is
an error using $foo as an array. So might make most sense to place the@
onas
, IMO, but I guess arguments could be made to place it like
@foreach ($foo as $bar)
orforeach @($foo as $bar)
.Regards,
AidanThanks for the great feedback.
Based on the last mindset on keyword syntax, this comes to mind, intended
to be used similarly to the 'use' keyword when used within the context of
a
closure:foreach ($foo as $bar) if (is_array) {
...
}I don't think this is a vast improvement over wrapping this within an
is_array check, however it does avoid the additional nest/wrapping. I was
hoping for something that reads a bit more concisely or with a bit more
syntactical sugar than the above. I think this does read nicely though.Cheers,
MarkOn Tue, Jul 11, 2017 at 1:50 PM Rowan Collins rowan.collins@gmail.com
wrote:For a syntactic
sugar/improvement, this can be shorthand for executing the loop instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the syntax
you suggest doesn't read quite right. As has been pointed out, this
differs
from existing features in two ways:
- the special handling is for any non-iterable value, not just null or
empty/falsey values, for which you could use $foo??[] and $foo?:[]
respectively- the handling is to skip the loop, not loop once assigning $bar to the
scalar value, as would happen with (array)$fooThe challenge, then, is to come up with some syntax that somehow
suggests
these rules. The "??" is too much like the null coalesce, which would be
misleading.The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire
someone else.Regards,
--
Rowan Collins
[IMSoP]
In theory you'd only need it be considered a suppressor? PHP already
exhibits the skipping behaviour (it only emits a warning for the wrong type
used in foreach
, skips the loop, and then continues with remaining code).
No harm in/there is probably value in, making that skipping intent explicit
in a RFC though, but in terms of a patch, the warning would only need be
suppressed as far as I can tell?
Another thing I meant to mention -- this should not only be useful for
arrays, but for any Traversable
too (i.e. it should suppress errors
generated in using a type not compatible with being iterated over in a
foreach
loop, and not just if the type is not array).
Kind regards,
Aidan
Aidan,
Fantastic suggestion (@as) -- that is really the succinctness I was
initially looking for, and I think the intention makes a lot of sense. My
only concern/issue would be to make sure that isn't considered a
'suppressor' -- but it's actual intent is to skip the execution of the
foreach to prevent the error/loop from occurring (rather than just
suppressing an error).Cheers,
MarkIf you were willing to accept
foreach ($foo as $bar) if (is_array) { ... }
as a solution, then you might as well use
if (is_array($foo)) foreach ($foo as $bar) { ... }
I wonder if this could be better achieved by expanding what the error
suppression operator@
can do? This entire behaviour seems more like an
error suppression action onforeach
to me, otherwise should we consider
coalescing operators for other types/creating a more generic one?Going back to the error suppression operator:
e.g. perhaps
foreach ($foo @as $bar) { ... }
could prevent skip past execution of the entire foreach block if there is
an error using $foo as an array. So might make most sense to place the@
onas
, IMO, but I guess arguments could be made to place it like
@foreach ($foo as $bar)
orforeach @($foo as $bar)
.Regards,
AidanThanks for the great feedback.
Based on the last mindset on keyword syntax, this comes to mind, intended
to be used similarly to the 'use' keyword when used within the context
of a
closure:foreach ($foo as $bar) if (is_array) {
...
}I don't think this is a vast improvement over wrapping this within an
is_array check, however it does avoid the additional nest/wrapping. I was
hoping for something that reads a bit more concisely or with a bit more
syntactical sugar than the above. I think this does read nicely though.Cheers,
MarkOn Tue, Jul 11, 2017 at 1:50 PM Rowan Collins rowan.collins@gmail.com
wrote:For a syntactic
sugar/improvement, this can be shorthand for executing the loop
instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the
syntax
you suggest doesn't read quite right. As has been pointed out, this
differs
from existing features in two ways:
- the special handling is for any non-iterable value, not just null or
empty/falsey values, for which you could use $foo??[] and $foo?:[]
respectively- the handling is to skip the loop, not loop once assigning $bar to the
scalar value, as would happen with (array)$fooThe challenge, then, is to come up with some syntax that somehow
suggests
these rules. The "??" is too much like the null coalesce, which would
be
misleading.The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire
someone else.Regards,
--
Rowan Collins
[IMSoP]
Hi Aidan,
I think you are correct on all points. The initial emit is just a warning,
so I think a suppressor will work just fine, since it does just pass over
the foreach if a traversable isn't passed in.
I could see this being helpful as it makes wrapping an if block around a
foreach not needed anymore (and in turn indenting the foreach another
level), replacing it with just a single character. I also think for those
that use linting tools and flag error suppressions, that an @as definition
could be easily ignored from such a linter. I develop with warnings on, and
see error suppressions as a sort of code smell, however I think the @as
definition could be really useful.
Cheers,
Mark
In theory you'd only need it be considered a suppressor? PHP already
exhibits the skipping behaviour (it only emits a warning for the wrong type
used inforeach
, skips the loop, and then continues with remaining code).No harm in/there is probably value in, making that skipping intent
explicit in a RFC though, but in terms of a patch, the warning would only
need be suppressed as far as I can tell?Another thing I meant to mention -- this should not only be useful for
arrays, but for anyTraversable
too (i.e. it should suppress errors
generated in using a type not compatible with being iterated over in a
foreach
loop, and not just if the type is not array).Kind regards,
AidanAidan,
Fantastic suggestion (@as) -- that is really the succinctness I was
initially looking for, and I think the intention makes a lot of sense. My
only concern/issue would be to make sure that isn't considered a
'suppressor' -- but it's actual intent is to skip the execution of the
foreach to prevent the error/loop from occurring (rather than just
suppressing an error).Cheers,
MarkOn Tue, Jul 11, 2017 at 4:05 PM Aidan Woods aidantwoods@gmail.com
wrote:If you were willing to accept
foreach ($foo as $bar) if (is_array) { ... }
as a solution, then you might as well use
if (is_array($foo)) foreach ($foo as $bar) { ... }
I wonder if this could be better achieved by expanding what the error
suppression operator@
can do? This entire behaviour seems more like an
error suppression action onforeach
to me, otherwise should we consider
coalescing operators for other types/creating a more generic one?Going back to the error suppression operator:
e.g. perhaps
foreach ($foo @as $bar) { ... }
could prevent skip past execution of the entire foreach block if there
is an error using $foo as an array. So might make most sense to place the
@
onas
, IMO, but I guess arguments could be made to place it like
@foreach ($foo as $bar)
orforeach @($foo as $bar)
.Regards,
AidanThanks for the great feedback.
Based on the last mindset on keyword syntax, this comes to mind,
intended
to be used similarly to the 'use' keyword when used within the context
of a
closure:foreach ($foo as $bar) if (is_array) {
...
}I don't think this is a vast improvement over wrapping this within an
is_array check, however it does avoid the additional nest/wrapping. I
was
hoping for something that reads a bit more concisely or with a bit more
syntactical sugar than the above. I think this does read nicely though.Cheers,
MarkOn Tue, Jul 11, 2017 at 1:50 PM Rowan Collins rowan.collins@gmail.com
wrote:For a syntactic
sugar/improvement, this can be shorthand for executing the loop
instead
of
wrapping the block within an is_array check:<?php
$foo = "abc";
foreach (??$foo as $bar) {
echo $bar;
}
Hi!
I think there's definitely the start of a good idea here, but the
syntax
you suggest doesn't read quite right. As has been pointed out, this
differs
from existing features in two ways:
- the special handling is for any non-iterable value, not just null or
empty/falsey values, for which you could use $foo??[] and $foo?:[]
respectively- the handling is to skip the loop, not loop once assigning $bar to
the
scalar value, as would happen with (array)$fooThe challenge, then, is to come up with some syntax that somehow
suggests
these rules. The "??" is too much like the null coalesce, which would
be
misleading.The only idea that immediately comes to mind is a keyword:
foreach ifarray ($foo as $bar) {
I can't say I'm that keen on that syntax, but maybe it will inspire
someone else.Regards,
--
Rowan Collins
[IMSoP]
Hi!
Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
Looks like $foo??[] would work here. If $foo is something like false or
null, that is. If it's not, this is probably a serious bug (why would
you iterate on something that is a number or a non-iterable object) and
should be either fixed or resolved explicitly, not hidden.
--
Stas Malyshev
smalyshev@gmail.com
Stas,
Wow, for some reason it didn't occur to me to try that. Confirming the
following works:
foreach ($foo ?? [] as $bar) {
echo $bar;
}
I think the biggest need for this is if the value is null. Guess it's
case-closed :)
Might be a good idea to add this to the docs, pretty neat.
Mark
On Wed, Jul 12, 2017 at 2:00 PM Stanislav Malyshev smalyshev@gmail.com
wrote:
Hi!
Code will error if a non-array value is passed through a looping feature.
For example, this code:<?php
$foo = "abc";
foreach ($foo as $bar) {
Looks like $foo??[] would work here. If $foo is something like false or
null, that is. If it's not, this is probably a serious bug (why would
you iterate on something that is a number or a non-iterable object) and
should be either fixed or resolved explicitly, not hidden.--
Stas Malyshev
smalyshev@gmail.com