rfc:foreach_void

PHP RFC: foreach iteration of keys without values

Introduction

When iterating with foreach, it is not possible to retrieve only the keys (and not also the values) without unnecessary extra work or semantic overhead. This RFC proposes new syntax that makes this possible.

Background

At present, there are two main patterns in use to iterate over all of the keys of an array, both of which have drawbacks:

foreach ($source as $key => $value) {
    // use the $key, ignore the $value
}

Retrieving the $value and ignoring it has a performance cost in that an opcode is emitted in compilation (and executed during iteration) to retrieve the value at each iteration. If the $value is never actually used, this is an unnecessary cost.

Additionally, there is a semantic cost, in that even though the $value is intended to be unused, it still exists. There is no clear indication strictly via code that the value is intended to be unused. Even when the variable is named accordingly, such as $unused, $dummy, $ignore, $_, etc, it is not always clear as to the intent. For example, $unused, $dummy, and $ignore could be all be an accurate representation of the meaning of an array's values.

foreach (array_keys($array) as $key) {
}

Retrieving the list of array keys for iteration in this manner is more semantically pure because it clearly indicates intent, but it involves a performance cost as a result of the call to array_keys. (An additional traversal of the array, as well as the time and memory cost of allocating/deallocating a new array to receive copies of the keys from the source array.)

Proposal

In order to iterate over an array (or generator, or other object that can be iterated) and retrieve only its keys, we add the following syntax:

foreach ($source as $key => void) {
}

By adding this syntax, we gain the ability to iterate over the keys in a performant and semantically appropriate manner.

By not having a target variable that receives the value, an opcode is no longer emitted (or executed) to copy that value from the source. This provides a minor performance enhancement at runtime at the expense of a slightly more complicated parser and compiler for foreach.

A new E_COMPILE_ERROR is also added. The error “foreach value target must be variable or void” is emitted if a key is requested and the value target specified is not a variable (or reference to a variable), or void.

Patches and Tests

The GitHub Pull Request for this change is here: https://github.com/php/php-src/pull/XXX

While in draft, the direct link to the relevant tree is: https://github.com/jbafford/php-src/tree/foreachvoid

Backward Incompatible Changes

None.

Proposed PHP Version(s)

Next PHP 7.x.

RFC Impact

There should be no adverse impact to SAPIs or existing extensions.

The only change to opcodes emitted is that when the foreach value target is void, the opcode that sets the target variable is omitted. Accordingly, there should be no adverse impact to opcache.

Open Issues

There are no open issues at this time.

Proposed Voting Choices

* Whether to add foreach ($source as $key => void) syntax

This proposal adds new syntax. Accordingly, it requires a 2/3 vote.

rfc/foreach_void.txt · Last modified: 2021/03/27 14:53 by ilutov