On سهشنبه ۱۸ اوت ۲۰۲۶، ۲۰:۳۴ Rowan Tommins [IMSoP] <[email protected]> wrote:
> On 18 August 2026 16:08:58 BST, "Rowan Tommins [IMSoP]" < > [email protected]> wrote: > >In fact, the simplest starting point would be no functions at all, just > an optimised ArraySliceIterator. The actual search part is fairly easy to > write in user code. > > > >Then in a separate RFC, add a new set of functions like "iter_search", > "iter_any", etc, which would be useful with *any* iterator, not just this > specific one. > > > Just to add, both ArraySliceIterator and iter_search can be implemented in > less than twenty lines of code each: <https://3v4l.org/HmYZV> > > Which is great for adding them natively: users of older versions or who > need to support multiple versions can "polyfill" them to start using > straight away, and then get more optimised versions when they upgrade. > > To be fair, the same is true of array_search_range: a memory-efficient > user implementation is simple, but can't be quite as time-efficient as an > internal one because it can't use optimisations based on the memory layout > of the array. Only lightly tested, but covers all of the proposed signature > in about 30 lines: <https://3v4l.org/VAsXY> > > For the archive, here's the sample implementations: > > ``` > class ArraySliceIterator implements IteratorAggregate { > private LimitIterator $backingIterator; > > public function __construct(array $array, int $offset, int $limit) > { > $this->backingIterator = new LimitIterator( > new ArrayIterator($array), > $offset, > $limit > ); > } > > public function getIterator(): Traversable > { > return $this->backingIterator; > } > } > > function iter_search(mixed $needle, iterable $haystack, bool $strict = > false): int|string|false > { > foreach ( $haystack as $key => $value ) { > if ( > ( $strict && $value === $needle ) > || > ( ! $strict && $value == $needle ) > ) { > return $key; > } > } > return false; > } > > function array_search_range( > mixed $needle, > array $haystack, > int $offset = 0, > ?int $length = null, > bool $strict = false, > ): int|string|false { > if ( $offset < 0 ) { > $offset = count($haystack) + $offset; > } > if ( $length < 0 ) { > $length = count($haystack) + $length - $offset; > } > > $currentOffset = -1; > foreach ( $haystack as $key => $value ) { > $currentOffset++; > if ( $currentOffset < $offset ) { > continue; > } > if ( $length !== null && $currentOffset >= $offset + > $length ) { > break; > } > if ( > ( $strict && $value === $needle ) > || > ( ! $strict && $value == $needle ) > ) { > return $key; > } > } > return false; > } > ``` > > Regards, > > Rowan Tommins > [IMSoP] > ‐-------- Hey Rowan, Man, I owe you one — seriously, thanks a lot for this! Your point about the polyfill was genuinely brilliant. It actually made me realize I was overcomplicating things. I went ahead and added a “Polyfill” section to the RFC, so anyone on an older PHP version can just copy-paste it and start using the function right away. No blockers for adoption anymore. And you hit the nail on the head about the memory layout thing — that’s exactly why the native version still matters. The userland polyfill is memory-friendly, but it walks element-by-element through the iterator. The internal one goes straight at the HashTable and stops the moment it finds a match. That’s the whole story in one sentence, honestly. Here’s the updated RFC: https://wiki.php.net/rfc/array_search_range Would love to hear what you think of the new section. Cheers, Sepehr >
