Re: [RFC] array_search_range() function

From: Date: Tue, 18 Aug 2026 18:32:08 +0000
Subject: Re: [RFC] array_search_range() function
References: 1 2 3 4 5 6 7 8  Groups: php.internals 
Request: Send a blank email to internals+get-132268@lists.php.net to get a copy of this message
On سه‌شنبه ۱۸ اوت ۲۰۲۶، ۲۰:۳۴ Rowan Tommins [IMSoP] <imsop.php@rwec.co.uk> wrote: > On 18 August 2026 16:08:58 BST, "Rowan Tommins [IMSoP]" < > imsop.php@rwec.co.uk> 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 >

« previous php.internals (#132268) next »