Re: [PHP-DEV] [RFC] array_search_range() function

[email protected] (سپهر محمودی)
Newsgroups php.internals
Message-ID <CA+Jcf5vAQfUzcbTgrC2-AmhnqpZ4_FzDp=9Vx48_xmaqJpxTLA@mail.gmail.com>
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

>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.