This is a new thread for John Bafford's RFC which he mentioned on another thread, see below:
https://wiki.php.net/rfc/foreach_void https://wiki.php.net/rfc/foreach_void
Hi Riikka,
A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch (https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I think) that helps with this, by allowing the following syntax:
foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve the values at all.
In theory, this should be a general performance win any time one needs to iterate over only the keys of an iterable, because it does not require the use of an O(n) iteration and building of the array that
array_keys()
would, plus it works on non-array types (such as generators or iterators). It also is more performant than foreach($iterable as $key => $_) {}, because it omits the opcode that instructs the engine to retrieve the value. (Presumably, a future direction could include using this request to inform generators or iterators to only return keys, and not values, which could further improve performance, especially if value generation is expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major objections to the idea, then after 8.0 is released, I can move the RFC out of Draft and into Under Discussion, and presuming a vote passes, I'll update the patch as necessary to work against 8.0. But my time is limited and I'm not willing to put further time into the code unless an RFC vote passes.
Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to update that?
-Mike
An alternative syntax would be
foreach($iterable as $key => _) { ... }
Using underscore as a way to signal "I don't care about this value".
Same could be possible with list destructoring, like
[_, _, $something] = foo();
This syntax comes from OCaml. Possibly other languages, too? Not sure.
2020-09-02 3:15 GMT, Mike Schinkel mike@newclarity.net:
This is a new thread for John Bafford's RFC which he mentioned on another
thread, see below:https://wiki.php.net/rfc/foreach_void
https://wiki.php.net/rfc/foreach_voidHi Riikka,
On Aug 31, 2020, at 14:13, Riikka Kalliomäki
riikka.kalliomaki@riimu.net wrote:A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch
(https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I
think) that helps with this, by allowing the following syntax:foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve
the values at all.In theory, this should be a general performance win any time one needs to
iterate over only the keys of an iterable, because it does not require the
use of an O(n) iteration and building of the array thatarray_keys()
would, plus it works on non-array types (such as generators or iterators).
It also is more performant than foreach($iterable as $key => $_) {},
because it omits the opcode that instructs the engine to retrieve the
value. (Presumably, a future direction could include using this request to
inform generators or iterators to only return keys, and not values, which
could further improve performance, especially if value generation is
expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major
objections to the idea, then after 8.0 is released, I can move the RFC out
of Draft and into Under Discussion, and presuming a vote passes, I'll
update the patch as necessary to work against 8.0. But my time is limited
and I'm not willing to put further time into the code unless an RFC vote
passes.Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to update
that?-Mike
An alternative syntax would be
foreach($iterable as $key => _) { ... }
Using underscore as a way to signal "I don't care about this value".
Same could be possible with list destructoring, like[_, _, $something] = foo();
This syntax comes from OCaml. Possibly other languages, too? Not sure.
The underscore is also used for this same purpose in both Python and
Javascript. However, it is a normal, valid variable name in those
languages. It is not in PHP.
I think I would prefer '_' over 'void' because of consistency with other
languages. However, we should also consider that:
- It is currently a valid constant name (BC break)
- It might be ambiguous in some contexts in which we may want to use it
in the future. We should carefully consider other possible use cases
like array destructuring.
Regards,
Dik Takken
This is a new thread for John Bafford's RFC which he mentioned on another
thread, see below:https://wiki.php.net/rfc/foreach_void <
https://wiki.php.net/rfc/foreach_void>
Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:
foreach ($iterable as $key => $_) { ... }
Introducing special syntax for this has costs, both in terms of language
complexity and in terms of implementation complexity. For example,
implementing this feature will make foreach (whether or not the value is
ignored) marginally slower, because we will have to explicitly distinguish
this case. (Or alternatively, we'd have to specialize and increase VM code
size -- it's not free in any case.)
Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant). The only potential
advantage to a dedicated syntax that I see is that there could be iterators
that can cheaply produce keys, but have expensive to produce values. That
seems like an edge case of an edge case though, and is a situation where
manually calling ->key() would be justifiable.
Regards,
Nikita
Hi Riikka,
On Aug 31, 2020, at 14:13, Riikka Kalliomäki <
riikka.kalliomaki@riimu.net> wrote:A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch (
https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I
think) that helps with this, by allowing the following syntax:foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve
the values at all.In theory, this should be a general performance win any time one needs
to iterate over only the keys of an iterable, because it does not require
the use of an O(n) iteration and building of the array thatarray_keys()
would, plus it works on non-array types (such as generators or iterators).
It also is more performant than foreach($iterable as $key => $_) {},
because it omits the opcode that instructs the engine to retrieve the
value. (Presumably, a future direction could include using this request to
inform generators or iterators to only return keys, and not values, which
could further improve performance, especially if value generation is
expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major
objections to the idea, then after 8.0 is released, I can move the RFC out
of Draft and into Under Discussion, and presuming a vote passes, I'll
update the patch as necessary to work against 8.0. But my time is limited
and I'm not willing to put further time into the code unless an RFC vote
passes.Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to
update that?-Mike
+1.
I'd also like to mention that other languages don't have any kind of
syntactic sugar/special syntax for iterating over keys. That is achieved
using a function though.
This proposal to me seems a bit like the "return if/guard" RFC i. e. I see
no value in it.
This is a new thread for John Bafford's RFC which he mentioned on another
thread, see below:https://wiki.php.net/rfc/foreach_void <
https://wiki.php.net/rfc/foreach_void>Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
Introducing special syntax for this has costs, both in terms of language
complexity and in terms of implementation complexity. For example,
implementing this feature will make foreach (whether or not the value is
ignored) marginally slower, because we will have to explicitly distinguish
this case. (Or alternatively, we'd have to specialize and increase VM code
size -- it's not free in any case.)Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant). The only potential
advantage to a dedicated syntax that I see is that there could be iterators
that can cheaply produce keys, but have expensive to produce values. That
seems like an edge case of an edge case though, and is a situation where
manually calling ->key() would be justifiable.Regards,
NikitaHi Riikka,
On Aug 31, 2020, at 14:13, Riikka Kalliomäki <
riikka.kalliomaki@riimu.net> wrote:A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch (
https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I
think) that helps with this, by allowing the following syntax:foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve
the values at all.In theory, this should be a general performance win any time one needs
to iterate over only the keys of an iterable, because it does not require
the use of an O(n) iteration and building of the array thatarray_keys()
would, plus it works on non-array types (such as generators or
iterators).
It also is more performant than foreach($iterable as $key => $_) {},
because it omits the opcode that instructs the engine to retrieve the
value. (Presumably, a future direction could include using this request
to
inform generators or iterators to only return keys, and not values, which
could further improve performance, especially if value generation is
expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major
objections to the idea, then after 8.0 is released, I can move the RFC
out
of Draft and into Under Discussion, and presuming a vote passes, I'll
update the patch as necessary to work against 8.0. But my time is limited
and I'm not willing to put further time into the code unless an RFC vote
passes.Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to
update that?-Mike
Hi Benas IML,
I'd also like to mention that other languages don't have any kind of
syntactic sugar/special syntax for iterating over keys. That is achieved
using a function though.
That's not true, Golang has iterating over keys by default and a more verbose syntax to iterate over values.
https://gobyexample.com/range
_
is used to indicate to the compiler that the result should be discarded.
// range on map iterates over key/value pairs.
kvs := map[string]string{"a": "apple", "b": "banana"}
for k, v := range kvs {
fmt.Printf("%s -> %s\n", k, v)
}
// iterate over just the keys of a map.
for k := range kvs {
fmt.Println("key:", k)
}
// iterate over just the values of a map.
for _, v := range kvs {
fmt.Println("key:", k)
}
Cheers,
- Tyson
This is a new thread for John Bafford's RFC which he mentioned on another
thread, see below:https://wiki.php.net/rfc/foreach_void <
https://wiki.php.net/rfc/foreach_void>Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
Introducing special syntax for this has costs, both in terms of language
complexity and in terms of implementation complexity. For example,
implementing this feature will make foreach (whether or not the value is
ignored) marginally slower, because we will have to explicitly distinguish
this case. (Or alternatively, we'd have to specialize and increase VM code
size -- it's not free in any case.)
There were two justifications given in the RFC. The first was that $key =>
$value and ignoring the value has performance costs. You indicate there
would be a cost to dealing with a special character there in order to know
whether or not to ignore the value. So, I think the question is which one
causes the bigger performance hit.
The other justification was semantic. I don't personally find that
justification for the change, especially if we could actually be looking at
performance implications.
Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant). The only potential
advantage to a dedicated syntax that I see is that there could be iterators
that can cheaply produce keys, but have expensive to produce values. That
seems like an edge case of an edge case though, and is a situation where
manually calling ->key() would be justifiable.Regards,
NikitaHi Riikka,
On Aug 31, 2020, at 14:13, Riikka Kalliomäki <
riikka.kalliomaki@riimu.net> wrote:A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch (
https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I
think) that helps with this, by allowing the following syntax:foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve
the values at all.In theory, this should be a general performance win any time one needs
to iterate over only the keys of an iterable, because it does not require
the use of an O(n) iteration and building of the array thatarray_keys()
would, plus it works on non-array types (such as generators or
iterators).
It also is more performant than foreach($iterable as $key => $_) {},
because it omits the opcode that instructs the engine to retrieve the
value. (Presumably, a future direction could include using this request
to
inform generators or iterators to only return keys, and not values, which
could further improve performance, especially if value generation is
expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major
objections to the idea, then after 8.0 is released, I can move the RFC
out
of Draft and into Under Discussion, and presuming a vote passes, I'll
update the patch as necessary to work against 8.0. But my time is limited
and I'm not willing to put further time into the code unless an RFC vote
passes.Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to
update that?-Mike
--
Chase Peeler
chasepeeler@gmail.com
Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
While this works fine, it does introduce an unused variable. Code
inspection currently complains about that, and for good reason, which is
annoying.
Even if we decide that it is not worth the trouble for foreach loops,
there are other cases where this new syntax can work well. Array
destructuring has already been mentioned.
Another case is the one where a function intentionally does not use one
of the arguments passed to it. This happens easily when using callbacks
or when implementing interfaces. A function declaration could look like
this:
function foo($arg, void) {}
This indicates that the second parameter is intentionally left unused.
Perhaps it is a good idea to generalize the RFC to the general concept
of "using void to intentionally ignore a variable". Maybe pick just one
use case for actual implementation and extend later using followup RFCs.
Regards,
Dik Takken
Even if we decide that it is not worth the trouble for foreach loops,
there are other cases where this new syntax can work well. Array
destructuring has already been mentioned.
Replying to myself: It just occurred to me that array destructuring
already allows omitting values:
[, , $username] = getUserData();
I still do find using void here more clear though, more intentional.
Another case is the one where a function intentionally does not use one
of the arguments passed to it. This happens easily when using callbacks
or when implementing interfaces. A function declaration could look like
this:function foo($arg, void) {}
Given the array destructuring syntax, an alternative syntax might be:
function foo($arg,)
Again, I would prefer to see void here in stead of a trailing comma. In
function calls a trailing comma is already allowed and it has a
completely different meaning, which can be confusing.
Regards,
Dik Takken
Even if we decide that it is not worth the trouble for foreach loops,
there are other cases where this new syntax can work well. Array
destructuring has already been mentioned.Replying to myself: It just occurred to me that array destructuring
already allows omitting values:[, , $username] = getUserData();
I still do find using void here more clear though, more intentional.
Yes, the current syntax lacks explicit intent and looks like a syntax
error. Anything would be better than this, I think. :)
Another case is the one where a function intentionally does not use one
of the arguments passed to it. This happens easily when using callbacks
or when implementing interfaces. A function declaration could look like
this:function foo($arg, void) {}
Given the array destructuring syntax, an alternative syntax might be:
function foo($arg,)
Again, I would prefer to see void here in stead of a trailing comma. In
function calls a trailing comma is already allowed and it has a
completely different meaning, which can be confusing.Regards,
Dik Takken--
To unsubscribe, visit: https://www.php.net/unsub.php
Regarding the unused variable, I think OPCache should be able to identify and eliminate it. I don't think it's necessary to add a new syntax here.
Array destructuring sounds like a similar case to me. If you don't like [, , $v] =$arr, you can use [$, $, $v]=$arr instead.
Regards,
CHU Zhaowei
-----Original Message-----
From: Dik Takken dik.takken@gmail.com
Sent: Thursday, September 3, 2020 3:31 AM
To: Nikita Popov nikita.ppv@gmail.com; Mike Schinkel mike@newclarity.net
Cc: John Bafford jbafford@zort.net; PHP internals internals@lists.php.net
Subject: Re: [PHP-DEV] Draft RFC: foreach iteration of keys without values
Just like the first time this was discussed, I don't think this RFC
makes a sufficient case on why we need explicit syntax for this. Just
ignoring the value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
While this works fine, it does introduce an unused variable. Code inspection currently complains about that, and for good reason, which is annoying.
Even if we decide that it is not worth the trouble for foreach loops, there are other cases where this new syntax can work well. Array destructuring has already been mentioned.
Another case is the one where a function intentionally does not use one of the arguments passed to it. This happens easily when using callbacks or when implementing interfaces. A function declaration could look like
this:
function foo($arg, void) {}
This indicates that the second parameter is intentionally left unused.
Perhaps it is a good idea to generalize the RFC to the general concept of "using void to intentionally ignore a variable". Maybe pick just one use case for actual implementation and extend later using followup RFCs.
Regards,
Dik Takken
--
To unsubscribe, visit: https://www.php.net/unsub.php
Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant).
The reason I in my previous message suggested the engine optimization
for the "foreach (array_keys($array) as $val)", is because I feel that
iterating over the keys of arrays is, in my experience, a relatively
common pattern. The reason is that array keys are occasionally used
for storing things like strings or numbers, especially when you need a
simple to implement unique list. On the other hand, I have never had
the need to specifically iterate over the keys of an iterator.
Additionally, I feel that there are other advantages to (at least)
implementing that optimization:
- The engine itself does not necessarily need to handle it differently
from normal foreach. Maybe the engine could, in fact, treat it just
like "foreach ($array as $val => $_)" - This is a pattern that I already see happening a lot in existing
code, so optimizing this case would give some benefits to existing
implementation - This would not require any changes to existing php syntax
- Should special syntax be introduced later, this case could be
converted into that syntax at that point
While the disadvantage of doing just this is that you can't easily
apply it to iterators, the thing is that iterators are already calling
other functions. The point here is to apply additional context
awareness to avoid unnecessary execution on existing language
constructs. I would see this more akin to dead code optimization than
a language feature.
This is a new thread for John Bafford's RFC which he mentioned on another
thread, see below:https://wiki.php.net/rfc/foreach_void <
https://wiki.php.net/rfc/foreach_void>Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
Introducing special syntax for this has costs, both in terms of language
complexity and in terms of implementation complexity. For example,
implementing this feature will make foreach (whether or not the value is
ignored) marginally slower, because we will have to explicitly distinguish
this case. (Or alternatively, we'd have to specialize and increase VM code
size -- it's not free in any case.)Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant). The only potential
advantage to a dedicated syntax that I see is that there could be iterators
that can cheaply produce keys, but have expensive to produce values. That
seems like an edge case of an edge case though, and is a situation where
manually calling ->key() would be justifiable.Regards,
NikitaHi Riikka,
On Aug 31, 2020, at 14:13, Riikka Kalliomäki <
riikka.kalliomaki@riimu.net> wrote:A common pattern that I've seen that could dearly use PHP internal
optimization, if possible, would be:foreach (array_keys($array) as $key) {
}I have a draft RFC (https://wiki.php.net/rfc/foreach_void) and patch (
https://github.com/jbafford/php-src/tree/foreachvoid against php 7.0, I
think) that helps with this, by allowing the following syntax:foreach($iterable as $key => void) { ... }
This would iterate over the keys of the iterable, and does not retrieve
the values at all.In theory, this should be a general performance win any time one needs
to iterate over only the keys of an iterable, because it does not require
the use of an O(n) iteration and building of the array thatarray_keys()
would, plus it works on non-array types (such as generators or iterators).
It also is more performant than foreach($iterable as $key => $_) {},
because it omits the opcode that instructs the engine to retrieve the
value. (Presumably, a future direction could include using this request to
inform generators or iterators to only return keys, and not values, which
could further improve performance, especially if value generation is
expensive. But that is out of scope for this RFC.)If this is something we'd like for PHP 8.1 and there are no major
objections to the idea, then after 8.0 is released, I can move the RFC out
of Draft and into Under Discussion, and presuming a vote passes, I'll
update the patch as necessary to work against 8.0. But my time is limited
and I'm not willing to put further time into the code unless an RFC vote
passes.Thoughts anyone?
+1 from me.
BTW, your RFC says "Next PHP 7.x" for Proposed Version; might need to
update that?-Mike
--
Riikka Kalliomäki
https://github.com/Riimu
Le Wed, 2 Sep 2020 19:13:20 +0200,
Nikita Popov nikita.ppv@gmail.com a écrit :
Just like the first time this was discussed, I don't think this RFC makes a
sufficient case on why we need explicit syntax for this. Just ignoring the
value is an existing pattern that works across all PHP versions:foreach ($iterable as $key => $_) { ... }
I currently use foreach (array_keys($array) as $key) { ... }
to avoid complains from code analysers on unused var, is it slower?
One obvious pro of having a dedicated syntax is not having to ask those
questions to ourselves while coding.
Iterating over just the keys is not a super common pattern and we already
have a reasonable way to do it (that is imho just as clear, and actually
more concise than the proposed "null" variant). The only potential
advantage to a dedicated syntax that I see is that there could be iterators
that can cheaply produce keys, but have expensive to produce values. That
seems like an edge case of an edge case though, and is a situation where
manually calling ->key() would be justifiable.
In our code base I thinks it is quite common.
grepping on "foreach (array_keys" gives me 51 cases, while grepping "foreach ("
gives me 1153, so that’s 4% of our foreach uses.
Côme
Hi,
foreach ($iterable as $key => $_) { ... }
I currently use foreach (array_keys($array) as $key) { ... }
to avoid complains from code analysers on unused var, is it slower?
one argument brought forward initially (sorry, can't find the email
right now) is the resource management: array_keys()
has to create a copy
[*] which might be an issue depending on the size of data.
- Markus
[*] I now about shallow-copy, I'm just trying to cite the initial
argument as best as I can :)
I currently use foreach (array_keys($array) as $key) { ... }
to avoid complains from code analysers on unused var, is it slower?one argument brought forward initially (sorry, can't find the email
right now) is the resource management:array_keys()
has to create a copy
[*] which might be an issue depending on the size of data.
While I like the idea of more explicit syntax to show intent over a mere
convention of $_ being an ignorable var, I do need to call out the foreach
(array_keys(...) argument as being a poor motivator.
IF (and I heavily stress "if" here) this pattern is common among people
trying to show explicit intent and IF it represents a noticeable slowdown,
then the solution for it is for the engine to optimize around that by
transforming it during compile time. That lets us fix all usages
instantaneously without user interaction, and more importantly it allows
users to focus on their code being readable (and thereby maintainable)
according to whatever coding standards they choose to apply.
Again, that same argument is why I actually like the proposal overall. Not
because it's so much more performant, but because it empowers developers to
write code in a way that will be most readable and maintainable to them,
should they happen to just not like the $_ unused var pattern (which is a
legit thing to dislike).
-Sara
I currently use foreach (array_keys($array) as $key) { ... }
to avoid complains from code analysers on unused var, is it slower?one argument brought forward initially (sorry, can't find the email
right now) is the resource management:array_keys()
has to create a copy
[*] which might be an issue depending on the size of data.While I like the idea of more explicit syntax to show intent over a mere
convention of $_ being an ignorable var, I do need to call out the foreach
(array_keys(...) argument as being a poor motivator.IF (and I heavily stress "if" here) this pattern is common among people
trying to show explicit intent and IF it represents a noticeable slowdown,
then the solution for it is for the engine to optimize around that by
transforming it during compile time. That lets us fix all usages
instantaneously without user interaction, and more importantly it allows
users to focus on their code being readable (and thereby maintainable)
according to whatever coding standards they choose to apply.Again, that same argument is why I actually like the proposal overall. Not
because it's so much more performant, but because it empowers developers to
write code in a way that will be most readable and maintainable to them,
should they happen to just not like the $_ unused var pattern (which is a
legit thing to dislike).-Sara
Question for those who know about opcache optimizations: is it
feasible to avoid fetching the current value if the value is otherwise
unused and the variable-variable features are not used either?
Do you think that it could be proxied? I mean, optimize foreach
(array_keys()...) syntax to not call array_keys()
in fact, but a optimized
version of foreach to handle key only. I don't know it opcache could do
that, and if it already does.
Em qui, 3 de set de 2020 12:12, Levi Morrison via internals <
internals@lists.php.net> escreveu:
On Thu, Sep 3, 2020 at 4:19 AM Markus Fischer markus@fischer.name
wrote:I currently use foreach (array_keys($array) as $key) { ... }
to avoid complains from code analysers on unused var, is it slower?one argument brought forward initially (sorry, can't find the email
right now) is the resource management:array_keys()
has to create a
copy
[*] which might be an issue depending on the size of data.While I like the idea of more explicit syntax to show intent over a mere
convention of $_ being an ignorable var, I do need to call out the
foreach
(array_keys(...) argument as being a poor motivator.IF (and I heavily stress "if" here) this pattern is common among people
trying to show explicit intent and IF it represents a noticeable
slowdown,
then the solution for it is for the engine to optimize around that by
transforming it during compile time. That lets us fix all usages
instantaneously without user interaction, and more importantly it allows
users to focus on their code being readable (and thereby maintainable)
according to whatever coding standards they choose to apply.Again, that same argument is why I actually like the proposal overall.
Not
because it's so much more performant, but because it empowers developers
to
write code in a way that will be most readable and maintainable to them,
should they happen to just not like the $_ unused var pattern (which is a
legit thing to dislike).-Sara
Question for those who know about opcache optimizations: is it
feasible to avoid fetching the current value if the value is otherwise
unused and the variable-variable features are not used either?--
To unsubscribe, visit: https://www.php.net/unsub.php
On Thu, Sep 3, 2020 at 5:35 PM David Rodrigues david.proweb@gmail.com
wrote:
Question for those who know about opcache optimizations: is it
feasible to avoid fetching the current value if the value is otherwise
unused and the variable-variable features are not used either?
TBH, this sounds like the best approach: optimizing the foreach (\array_keys($input) as $key) {
structure, when detected.
That would make it zero impact from an RFC/userland perspective, and the OP
by John is in fact about a performance concern, while we already have a
very expressive way to do key iteration.
Marco Pivetta
On Thu, Sep 3, 2020 at 10:35 AM David Rodrigues david.proweb@gmail.com
wrote:
Do you think that it could be proxied? I mean, optimize foreach
(array_keys()...) syntax to not callarray_keys()
in fact, but a optimized
version of foreach to handle key only. I don't know it opcache could do
that, and if it already does.
I wouldn't use the word "proxied", but yes. In my mind the compiler would
see:
foreach(\array_keys($arr) as $key) {
and quietly transform that into:
foreach ($arr as $key => $_unusedVariableNameThatIsntEvenSpilledToTheScope)
{
Thus not iterating the array twice and creating a temporary array of key
names.
-Sara
On Thu, Sep 3, 2020 at 10:35 AM David Rodrigues david.proweb@gmail.com
wrote:Do you think that it could be proxied? I mean, optimize foreach
(array_keys()...) syntax to not callarray_keys()
in fact, but a
optimized
version of foreach to handle key only. I don't know it opcache could do
that, and if it already does.I wouldn't use the word "proxied", but yes. In my mind the compiler would
see:foreach(\array_keys($arr) as $key) {
and quietly transform that into:
foreach ($arr as $key => $_unusedVariableNameThatIsntEvenSpilledToTheScope)
{Thus not iterating the array twice and creating a temporary array of key
names.
Good idea; since I'm kind of bored, I'll try to implement a prototype
myself during my free time.
-Sara
On Thu, Sep 3, 2020 at 10:35 AM David Rodrigues david.proweb@gmail.com
wrote:Do you think that it could be proxied? I mean, optimize foreach
(array_keys()...) syntax to not callarray_keys()
in fact, but a
optimized
version of foreach to handle key only. I don't know it opcache could do
that, and if it already does.I wouldn't use the word "proxied", but yes. In my mind the compiler would
see:foreach(\array_keys($arr) as $key) {
and quietly transform that into:
foreach ($arr as $key => $_unusedVariableNameThatIsntEvenSpilledToTheScope)
{
Are there other instances where we have optimizations like this? If so, are
they documented?
In terms of readability, I'm more likely to do
$keys = array_keys($array);
foreach($keys as $key){
That would obviously break the optimization we're talking about though.
Which makes me wonder if there are other places like that.
Thus not iterating the array twice and creating a temporary array of key
names.-Sara
--
Chase Peeler
chasepeeler@gmail.com
Introducing special syntax for this has costs, both in terms of language
complexity and in terms of implementation complexity. For example,
implementing this feature will make foreach (whether or not the value is
ignored) marginally slower, because we will have to explicitly distinguish
this case. (Or alternatively, we'd have to specialize and increase VM code
size -- it's not free in any case.)
Regarding the performance / complexity concern, just some possibly naive
idea from a non-expert: Could this not be implemented in the compilation
phase only, without changing any of the run time code? Maybe the 'void'
could be compiled into an opcode sequence that still introduces a
variable holding the keys. Execution remains unchanged. So the only
thing that 'void' does is ask PHP to implicitly create a hidden variable
in stead of the programmer explicitly creating a visible one.
Ok, now just say "That's nonsense" and I will shut up. :)
Regards,
Dik Takken
Hi!
In theory, this should be a general performance win any time one
needs to iterate over only the keys of an iterable, because it does
not require the use of an O(n) iteration and building of the array
thatarray_keys()
would, plus it works on non-array types (such as
generators or iterators). It also is more performant than
foreach($iterable as $key => $_) {}, because it omits the opcode
that instructs the engine to retrieve the value. (Presumably, a
future direction could include using this request to inform
generators or
To me, it looks like the case of premature micro-optimization. Unless
there's a benchmark that proves it achieves speedup in a real-life
application (not tight-loop synthetic benchmark) I think
foreach($iterable as $key => $_) {} is completely fine. My opinion has
been and remains, absent new data, that if your code performance hinges
on a couple of simple opcodes being there, maybe you'd better implement
that part in C, but in most real-life applications it is not and any
performance gain you might get from such syntax is microscopic.
--
Stas Malyshev
smalyshev@gmail.com
Hi!
In theory, this should be a general performance win any time one
needs to iterate over only the keys of an iterable, because it does
not require the use of an O(n) iteration and building of the array
thatarray_keys()
would, plus it works on non-array types (such as
generators or iterators). It also is more performant than
foreach($iterable as $key => $_) {}, because it omits the opcode
that instructs the engine to retrieve the value. (Presumably, a
future direction could include using this request to inform
generators orTo me, it looks like the case of premature micro-optimization. Unless
there's a benchmark that proves it achieves speedup in a real-life
application (not tight-loop synthetic benchmark) I think
foreach($iterable as $key => $_) {} is completely fine. My opinion has
been and remains, absent new data, that if your code performance hinges
on a couple of simple opcodes being there, maybe you'd better implement
that part in C, but in most real-life applications it is not and any
performance gain you might get from such syntax is microscopic.
If it adds a micro-optimization, great, but allowing a developer to explicitly signal intent is the primary argument for adding void. IMO.
-Mike
Hi!
If it adds a micro-optimization, great, but allowing a developer to
explicitly signal intent is the primary argument for adding void.
IMO.
You can signal intent by using $_ or $dummy or whatever. You don't need
new language construct each time for each way of using or not using a
variable.
--
Stas Malyshev
smalyshev@gmail.com
Hi all
I want to point out the use-case when you're using CS tools, static analysers and IDEs: they report unused variables as errors. There are ways around those errors, but it's more convenient if there's language support. I'd say that conceptually it's also more correct: if you're not using a variable, it shouldn't be there.
As some of you have shown, there are ways achieve the same result without adding new syntax. Just like we didn't need short closures and keep using the normal closure syntax, like we could write if statements and didn't need the nullsafe operator, like we didn't need named arguments or constructor property promotion. I think the past years of PHP devlopment have shown that the majority likes convenient langague syntax and constructs, not because it's absolutely necessary, but because it's just a little more clean, a little less verbose, a bit more convenient.
PHP has been maturing over the last years, which means there's room, and need, for things that aren't strictly necessary.
Kind regards
Brent
Hi!
If it adds a micro-optimization, great, but allowing a developer to
explicitly signal intent is the primary argument for adding void.
IMO.You can signal intent by using $_ or $dummy or whatever. You don't need
new language construct each time for each way of using or not using a
variable.--
Stas Malyshev
smalyshev@gmail.com--
To unsubscribe, visit: https://www.php.net/unsub.php
Hi all
I want to point out the use-case when you're using CS tools, static analysers and IDEs: they report unused variables as errors. There are ways around those errors, but it's more convenient if there's language support. I'd say that conceptually it's also more correct: if you're not using a variable, it shouldn't be there.
Exactly this.
The intent of a particular language construct does not only need to be
clear to human readers but also to machines. More explicit intent leads
to stronger static code analysis tools, which helps us catch more bugs
earlier.
Regards,
Dik Takken
Hi all
I want to point out the use-case when you're using CS tools, static
analysers and IDEs: they report unused variables as errors. There are ways
around those errors, but it's more convenient if there's language support.
I'd say that conceptually it's also more correct: if you're not using a
variable, it shouldn't be there.Exactly this.
The intent of a particular language construct does not only need to be
clear to human readers but also to machines. More explicit intent leads
to stronger static code analysis tools, which helps us catch more bugs
earlier.Regards,
Dik Takken
Static analysis tools don't need a language feature to support this. They
can recognize the $_ pattern and not emit an unused variable warning for
it. I'd suggest submitting a feature request.
Nikita
Hi all
I want to point out the use-case when you're using CS tools, static
analysers and IDEs: they report unused variables as errors. There are ways
around those errors, but it's more convenient if there's language support.
I'd say that conceptually it's also more correct: if you're not using a
variable, it shouldn't be there.Exactly this.
The intent of a particular language construct does not only need to be
clear to human readers but also to machines. More explicit intent leads
to stronger static code analysis tools, which helps us catch more bugs
earlier.Regards,
Dik TakkenStatic analysis tools don't need a language feature to support this. They
can recognize the $_ pattern and not emit an unused variable warning for
it. I'd suggest submitting a feature request.Nikita
I agree here. _ is already a common pattern in other languages for a placeholder ignored variable. It's not a big jump for PHP static analyzers to start ignoring unused $_ variables, and it requires no language changes or formal standards.
I am skeptical of any performance difference, but from a reader-communication point of view a de facto convention of $_ == unused, and analyzers recognizing that, seems like the path of least resistance.
--Larry Garfield
I agree here. _ is already a common pattern in other languages for a placeholder ignored variable. It's not a big jump for PHP static analyzers to start ignoring unused $_ variables, and it requires no language changes or formal standards.
Technically that will work. However, this needs to rely on some
unwritten undocumented convention that all of the user community agrees
on and is aware of. Such a convention can be established and documented
of course, it worked for doc comments as well.
Apparently the PHPMD project considered a change to recognize $_ as an
ignored variable. It was declined:
https://github.com/phpmd/phpmd/issues/326
In stead, configuration was added to allow specifying a variable name
that is to be ignored. Still, every individual user needs to manually
configure it and pick a name for ignored variables.
For one use case, using $_ simply does not appear to be an option, while
using void is. This is the use case of ignoring an argument that is
passed to a function:
function foo($_) {}
This can work but it changes the name of the parameter. That is not the
intent at all. It breaks in inheritance scenarios. When it is called and
the parameter name is specified as the parent defines it, a fatal error
results.
What I like about using void is that it has clear intent, it requires no
configuration of static analyzers and it provides a single syntax that
works for all use cases: foreach, destructuring and function parameters.
Regards,
Dik Takken