Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108769 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 4215 invoked from network); 26 Feb 2020 16:45:34 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 26 Feb 2020 16:45:34 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 75BEA180212 for ; Wed, 26 Feb 2020 07:03:13 -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=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS15169 209.85.128.0/17 X-Spam-Virus: No X-Envelope-From: Received: from mail-il1-f172.google.com (mail-il1-f172.google.com [209.85.166.172]) (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, 26 Feb 2020 07:03:12 -0800 (PST) Received: by mail-il1-f172.google.com with SMTP id x7so513739ilq.11 for ; Wed, 26 Feb 2020 07:03:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=YL5jpdntzOJbdVrX+lkAkSmo+qDo3y5VsyQp94FMBAg=; b=MiWgLzL33igsneFf1YlMfPcn61oSLGQnL08P6wEVA6V4UE25/2t92vrq82jy22C3q8 lD2dwapCf7uQJu9aJ+IDNoEOw1QEMfT0K4ONpGANc0kxzkGlFkN7PqQi5fDf50XlYfvn wNXu23ZBcM9i+15tDMmv7mq+28ID5A4L6gSIDEMQ+U1y3vuA8T2saDgrdXmFzS0NO9U2 npmO+PLyHsrJsEUClyGX6jNdncXdSn4ej60W1xQQsUQaOeatS3F/qIaxy40u1VVOglPn y/0rI+nhLEToK0cMArjZcGAAiOhwyXJ2fgm98QJWZ3wBPJ7Q/b8kyLOWQ/i98VJW5m/V ux2A== 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; bh=YL5jpdntzOJbdVrX+lkAkSmo+qDo3y5VsyQp94FMBAg=; b=tMqTpEV/CuoLUgnNhOnMqjtN0tIWZKHtlQ+2JJJnfMwjEr6mcSsgHLpE25RzigP/Ai 9xdb6L+mLu9RyHS2yRKPc9fTJnPhAdVfjXFS0DD6q/MnaqfbhhoYwpDnv+szFNeee7Gk 43FxqPUVuuk9WFpwKMm3A4JTCjXg3+cf2IYjLUXkV1Mev1CRBllSsg3zUoGOK/BKw7TR 1yPT3EIs7s9zyoHzPOPW+LhxlFqaqSW2dkcf5twR34xXjbjvLz65hVpV45VZ9UhZViFS VYWuOZqTZBgmIM98JtYM9v3zRUP+OZB4E994ankq0A4gW6cFGNTmp+y+2fadvWrSZn4d Ai5g== X-Gm-Message-State: APjAAAXz2UKsTF4UZZyAe6+DCtEjtRN6Wc1e7yWVsQOzA6vU+kHq/tOK 0OH8kxMAEQh3gNOGK17JUBpBgJg1X7ipGVGxw7cnwKXX X-Google-Smtp-Source: APXvYqwvD7ZIa+QvPLrDFR7tEFJaKdYfNhzevwqqJ5t+Iu9C0dolBkWjLykZ+hFxQBnnDc4BZEthpqLt21eO+bTV/vs= X-Received: by 2002:a92:7606:: with SMTP id r6mr5207826ilc.120.1582729392014; Wed, 26 Feb 2020 07:03:12 -0800 (PST) MIME-Version: 1.0 References: In-Reply-To: Date: Wed, 26 Feb 2020 15:03:00 +0000 Message-ID: To: PHP internals Content-Type: text/plain; charset="UTF-8" Subject: Re: [PHP-DEV] Support rewinding of generators From: rowan.collins@gmail.com (Rowan Tommins) Hi Nikita, On 26 February 2020 11:47:14 GMT+00:00, Nikita Popov wrote: >There is a relatively simple (at least conceptually) way to make generators >rewindable: Remember the original arguments of the function, and basically >"re-invoke" it on rewind(). This is an interesting idea. There is a gotcha though, neatly demonstrated by your example: >function map(callable $function, iterable $iterable): \Iterator { > foreach ($iterable as $key => $value) { > yield $key => $function($value); > } >} If the $iterable passed in is anything other than an array, re-invoking the function won't actually rewind it. That can be fixed by explicitly rewinding at the start: function map(callable $function, iterable $iterable): \Iterator { reset($iterable); foreach ($iterable as $key => $value) { yield $key => $function($value); } } But now we have a different problem: if we pass an iterator that doesn't support rewinding, we'll get an error immediately. In other cases, the side-effects of running the "constructor" itself might be undesirable. For instance, it might re-run an SQL query, rather than rewinding a cursor: public function getResultsIterator($sql) { $cursor = $this->runQuery($sql); foreach ( $cursor->getNext() as $row ) { yield $this->formatRow($row); } } I think the fix would be to return a generator rather than yielding directly, like this: public function getResultsIterator($sql) { $generator = function($cursor) { $cursor->rewind(); foreach ( $cursor->getNext() as $row ) { yield $this->formatRow($row); } }; $cursor = $this->runQuery($sql); return $generator($cursor); } In general, it feels like it would be useful for generators that knew it was going to happen, but a foot-gun for generators that weren't expecting it, so I like Judah's suggestion of an opt-in mechanism of some sort. Regards, -- Rowan Tommins [IMSoP]