Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:99695 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 84346 invoked from network); 3 Jul 2017 01:45:06 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 3 Jul 2017 01:45:06 -0000 Received: from [127.0.0.1] ([127.0.0.1:15798]) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ECSTREAM id 0A/D5-60825-1A1A9595 for ; Sun, 02 Jul 2017 21:45:05 -0400 Authentication-Results: pb1.pair.com smtp.mail=andreas@dqxtech.net; spf=permerror; sender-id=unknown Authentication-Results: pb1.pair.com header.from=andreas@dqxtech.net; sender-id=unknown Received-SPF: error (pb1.pair.com: domain dqxtech.net from 209.85.214.48 cause and error) X-PHP-List-Original-Sender: andreas@dqxtech.net X-Host-Fingerprint: 209.85.214.48 mail-it0-f48.google.com Received: from [209.85.214.48] ([209.85.214.48:35154] helo=mail-it0-f48.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id B0/92-60825-675E7595 for ; Sat, 01 Jul 2017 14:09:59 -0400 Received: by mail-it0-f48.google.com with SMTP id v202so73570950itb.0 for ; Sat, 01 Jul 2017 11:09:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech-net.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=Bag3FEqT2UJX7u7USucVgbxBWOuJUzYhjhc1IAdaZBw=; b=hnWqCaOwCip5eGTkaZxtxRYvFVCE1VPwfUre/V3V0URsC/cfxGh+NRcfE4l9Ds0Y8n 7S3wHWFJvx8l7SeGCqfQYF1DJMUuYRRPrGt0Mc/lW/iNjuK3In0cuUhU32MMljZYXK4S JvWxNcuPU8zW4bq3aozuZZrHM0141DjLmOCdZX8zgOFfrFju+yTM80+7pTijv8Dp36eb a2BlPb2S0GhtNnGswKuyAspBdLDnjY3REX/VDwAI8TP/L/RXu3ku6Xffsvy2noJW6wHS ttmyDLCTxKfRomVSUhudwdGCvMV9bVgkSjxhGgTgTkC2zyiqsH6ie/iVJfDxp3aF0NJD DjYg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=Bag3FEqT2UJX7u7USucVgbxBWOuJUzYhjhc1IAdaZBw=; b=Sl8sx12N6FHH4cPaCIWvGg1RYA7Gj57fLVuZS+fljKK5dCr+oh248NBKEHwhSfcx8g DWCngG3k5n3Je+qL16gA8RQizhcU0qUvbMnPnPo/IUczjuPfJ2GMU/OTXn9dXZjY3e/4 ipFZqlfi02QIwrPqV3SMpe3bZ3B32yuqNQK6lS9BqAkL8c6ExrFmWE+8JGVxxun+hGea 22NFcLFvE+9FqT4SYPNHGoab/KiEM81WzE6VG0Z+6R4fkgU0Av+dG3qvVHbwBCPfIsl2 KAKbzqhKrATPcKw9itPFeZWCkCLAE8zTEL1oAQsFm0dWTdzFQ0WUnXAOErpVX3ZmAd7M 43ww== X-Gm-Message-State: AIVw110Q++YTShUbP5HZpHqDkOiEafl94JH8pzDAeRJQs4tt99OKRZvU CDkpKf/oTJY17FZH1TY= X-Received: by 10.36.175.73 with SMTP id l9mr2008548iti.102.1498932595276; Sat, 01 Jul 2017 11:09:55 -0700 (PDT) Received: from mail-it0-f54.google.com (mail-it0-f54.google.com. [209.85.214.54]) by smtp.googlemail.com with ESMTPSA id k94sm6090227ioi.29.2017.07.01.11.09.54 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 01 Jul 2017 11:09:54 -0700 (PDT) Received: by mail-it0-f54.google.com with SMTP id m84so39309032ita.0 for ; Sat, 01 Jul 2017 11:09:54 -0700 (PDT) X-Received: by 10.36.214.7 with SMTP id o7mr1836797itg.53.1498932594385; Sat, 01 Jul 2017 11:09:54 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.246.71 with HTTP; Sat, 1 Jul 2017 11:09:34 -0700 (PDT) Date: Sat, 1 Jul 2017 20:09:34 +0200 X-Gmail-Original-Message-ID: Message-ID: To: internals@lists.php.net Content-Type: text/plain; charset="UTF-8" Subject: [PHP-DEV] "Reader" as alternative to Iterator From: andreas@dqxtech.net (Andreas Hennings) Hello internals, (this is my first email to this list, hopefully I'm doing ok.) (I sent this message before, but I think it was rejected due to html/multipart and lack of [PHP-DEV] in subject) -------------------------------------------------------------------------------- Background / motivation: Currently in PHP we have an interface "Iterator", and a final class "Generator" (and others) that implement it. Using an iterator in foreach () is straightforward: foreach ($iterator as $key => $value) {..} However, if we want to iterate only a portion and then continue elsewhere at the position where we stopped, we need to do something like this: for ($iterator->rewind(); $iterator->valid(); $iterator->next()) { $value = $iterator->current(); [..] } This is unpleasantly verbose, and also adds performance overhead due to additional function calls. Also, manually writing an iterator is quite painful. I sometimes implement "readers" that can be used like this (*): // Gets a reader at position zero. $reader = $readerProvider->getReader(); while (FALSE !== $value = $reader->read()) { [..] } (*) Note that I am using FALSE as an equivalent for "end of data". Of course it would be nice if we had a dedicated constant for this, that does not constrain the range of possible values of the iterator. Such readers are much easier to write than iterators. However, there is no native support for foreach(), and for generator syntax with yield. Adapters from Iterator to Reader and vice versa are possible to write. However, such userland adapters add additional performance overhead: One call to ->read() will trigger one call to ->valid(), one to ->current(), one to ->next(). -------------------------------------------------------------------------------- Proposal: Establish a new interface in core, "Reader" or "ReaderInterface" (*). This interface has only one method, "->read()". The existing interface Iterator will remain unchanged. (*) I am open to other naming suggestions. In fact in my own projects I called this thing "StreamInterface", and distinguish between "ObjectStreamInterface", "RowStreamInterface" etc. Currently I think "Reader" might be more suitable. Let the final class "Generator", and possibly other native iterators, implement Reader in addition to Iterator. Optionally, add an interface "ReaderAggregate", or "ReaderAggregateInterface", or "ReaderProvider". This interface has only one method, "getReader()". Let ReaderAggregate extend Traversable, and add foreach() support. The key will simply be a counter. Open questions: - The naming of "Reader", "ReaderAggregate", "->read()". - Which return value to use for "end of data", so that FALSE would become a valid value. I currently don't see a better option than FALSE. Maybe a sub-interface of ReaderAggregate can have an method "->getStopValue()", which would allow to specify something other than FALSE. -------------------------------------------------------------------------------- - Andreas Hennings (https://github.com/donquixote)