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