Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:113065 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 38800 invoked from network); 3 Feb 2021 16:26:19 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Feb 2021 16:26:19 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 7CF5D1804F2 for ; Wed, 3 Feb 2021 08:09:49 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-1.4 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM,HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-lf1-f50.google.com (mail-lf1-f50.google.com [209.85.167.50]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 3 Feb 2021 08:09:49 -0800 (PST) Received: by mail-lf1-f50.google.com with SMTP id h7so34145281lfc.6 for ; Wed, 03 Feb 2021 08:09:48 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc:content-transfer-encoding; bh=kJZB0ghV4htNebeov3HZcz456jZ52wpUe8atfYjaz3I=; b=cZRPk8iqVx+ubxtj6jk8Ds50r0op9D2CYeKxDC6lCbaE+iTEVlIe+V2TkMqTbWuNb/ osMWJMRyDexvk+zPAFqWnZKjatHtjEup6xRBf2AMHA7uIC9gBY2eUDpEVctAyQLsko0s Equ7CmU7c5V9mktl80l3QhJcTSRuA5O9cqwfkYg0wdNsZk2lgZjmSIjm2Q1VS5uCFjR8 NvmCgOZG9BF9apL2nvL0YSWMFjpuj70OF33LS9/YLI+oSNNYQfCNZuJKbBcBPng1AYk9 ekEYGy7IJy9QvpSrMep1fkOHkqp3eGrCYDoKyLEWnENPN1YsljHSD/xKNlouEIKVgEJr NiKg== X-Gm-Message-State: AOAM531vpmib+t7teKds7jOIBEreofAyd94NuZjUkMZOUDVxkPgA30ZH MOOVi7eMQA4kL0JhedqbE/vSrHOj/peyrKw/7yQ= X-Google-Smtp-Source: ABdhPJxpGeaLoFnge7nJeqdx6AETBC1CK45FgM59e/Ah/QH2BfYYLvA3C2sVGy2G2OWFnv19VRQUxqNlPcxiGZgDmO8= X-Received: by 2002:ac2:5b4f:: with SMTP id i15mr2111321lfp.191.1612368586557; Wed, 03 Feb 2021 08:09:46 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 3 Feb 2021 09:09:30 -0700 Message-ID: To: Nikita Popov Cc: internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] Proposal: Add ReverseArrayIterator and ForwardArrayIterator to SPL From: levim@php.net (Levi Morrison) On Wed, Feb 3, 2021 at 8:50 AM Nikita Popov wrote: > > On Wed, Feb 3, 2021 at 4:38 PM Levi Morrison wrote: >> >> Hello, everyone! >> >> This proposal adds two new classes to the SPL: >> >> - `Spl\ReverseArrayIterator`. It iterates over an array in reverse >> order. It does not duplicate the array. >> - `Spl\ForwardArrayIterator`. It iterates over an array in forward >> (normal) order. It does not duplicate the array. >> >> They both implement Countable which returns the `count()` of the >> array. The [PR][1] has some examples and discusses why I am proposing >> `ForwardArrayIterator` when there is already `ArrayIterator`, the >> short of which is for performance. There are timing numbers in [one of >> the comments][2]. >> >> When it comes time to vote I may merge this into another RFC with >> [`CachedIterable` by Tyson Andre][3], which I recommend readers also >> take a look at. Whether we team up for the RFC vote or not, I wanted >> to get this out there for discussion and review. >> >> [1]: https://github.com/php/php-src/pull/6535 >> [2]: https://github.com/php/php-src/pull/6535#issuecomment-769179450 >> [3]: https://github.com/php/php-src/pull/6655 > > > Hey Levi, > > I like the general idea of having an "ArrayIterator but sane". > > That said, I don't think that the ReverseArrayIterator + ForwardArrayIter= ator pair of iterators approaches this problem correctly. There are plenty = of iterators that could be run in reverse, and I think it would be silly to= create two classes for each of them. E.g. if we introduce an ObjectPropert= yIterator, should there be both ForwardObjectPropertyIterator and ReverseOb= jectPropertyIterator? I don't think so. > > I think the correct abstraction for bidirectional iterators is to introdu= ce an interface > > // Or "ReversibleIterator" > interface BidrectionalIterator extends Iterator { > public function prev(): void; > public function end(): void; > } > > and then a class along the lines of: > > class ReverseIterator implements BidirectionalIterator { > public function __construct(private BidirectionalIterator $iter) {} > > public function next() { $this->iter->prev(); } > // etc. > } > > This would replace "new ReverseArrayIterator($array)" with "new ReverseIt= erator(new ArrayIterator($array))", but in a way that is general, and compo= ses. > > Regards, > Nikita I wrote an implementation of this idea two years ago: https://github.com/php/php-src/compare/master...morrisonlevi:BidirectionalA= rrayIterator It's fine for arrays, but not all structures that you can iterate through forward or reverse. For instance, tree structures can be traversed forward or reverse, but bidirectionally is far more difficult (and I did not find any pre-existing solutions in this space, btw). I do have repositories with tree structures, so it's not just theoretical. Another factor for abandonment was ergonomics. This is not great: `new ReverseIterator(new BidirectionalArrayIterator($array))`. It's mildly less performant as well, having to create two objects, and then having delegation through methods. Let me know if you think of any way to reconcile these issues, and I'll do the same.