Addendum to my example:

If my get_tcp_header was made a class it would also be possible for it to
support the `__advance__` protocol:
```
class TCPHeaderIter(Iterator[TCPHeader]):
    def __init__(self, stream: Iterator[Byte]):
        self.stream = stream

    def __next__(self) -> TCPHeader:
        # similar to the body of the while loop

    def __advance__(self, n):
        for _ in range(n):
            self.stream.advance(2)
            total_length = ...
            self.stream.advance(total_length - 4)
```
Now I don't have a use case for `__advance__` on a TCP header iterator but
one might
want to sample every N'th header.



On Wed, Oct 7, 2020 at 3:06 PM Caleb Donovick <donov...@cs.stanford.edu>
wrote:

> > For `__advance__` to be an official Python protocol, it would almost
> > certainly have to be of use for *general purpose iterators*, not just
> > specialised ones -- and probably not *hypothetical* iterators which may
> > not even exist. Do you have concrete examples of your skip list and tree
> > iterators that are in wide-spread use?
>
> "I am +0.3 on this as I don't personally have a need"
> " (I'm not sure why you would ever want to `__advance__` a tree iterator)"
>
> > What's your use case for advancing a count object, rather than just
> > creating a new one?
>
> Itertools.count was an example (hence the use of "e.g.") of an iterator
> which can be efficiently
> advanced without producing intermediate state. Clearly anyone can advance
> it manually.
> My point is that an iterator may have an efficient way to calculate its
> state some point in the future
> without needing to calculate the intermediate state.  For example the
> fibonacci sequence has a closed
> form formula for the nth element and hence could be advanced efficiently.
>
> I realize my original examples were contrived, but I have a better one.
> Consider the task of collecting TCP headers from an iterator of bytes:
>
> ```
> def get_tcp_headers(stream: Iterator[Byte]):
>     while stream:
>         # Move to the total length field of the IP header
>         stream.advance(2)
>         # record the total length (two bytes)
>         total_length = ...
>         # skip the rest of IP header
>         stream.advance(28)
>         # record the TCP header
>         header = ...
>         yield header
>         stream.advance(total_length - 32 - len(header))
> ```
>
> Maybe Kevin can tell us what motivated him to post this idea but I can see
> many places in parsing where you might want
> to skip arbitrary portions of a stream.  The beauty of iterators is you
> don't need to be concerned with the underlying data
>  structure. Ideally I shouldn't need to write two versions of some parse
> function one which operates on sequences and one
> that operates on iterables, just so I can efficiently `advance` the
> sequences.
>
> -- Caleb Donovick
>
> On Tue, Oct 6, 2020 at 6:16 PM Steven D'Aprano <st...@pearwood.info>
> wrote:
>
>> On Tue, Oct 06, 2020 at 02:27:54PM -0700, Caleb Donovick wrote:
>> > I am +0.3 on this as I don't personally have a need for this but do see
>> the
>> > utility.
>> >
>> > I can think of a number of examples where an `__advance__` would be
>> > preferable to any of the proposed solutions:
>> [...]
>>
>> For `__advance__` to be an official Python protocol, it would almost
>> certainly have to be of use for *general purpose iterators*, not just
>> specialised ones -- and probably not *hypothetical* iterators which may
>> not even exist. Do you have concrete examples of your skip list and tree
>> iterators that are in wide-spread use?
>>
>> Specialised iterators can create whatever extra APIs they want to
>> support, but the official iterator protocol intentionally has a very
>> basic API:
>>
>> - anything with an `__iter__` method which returns itself;
>> - and a `__next__` method that returns the next value, raising
>>   StopIteration when exhausted.
>>
>> This is a bare minimum needed to make an iterator, and we like it that
>> way. For starters, it means that generators are iterators.
>>
>> If people want to supply objects that support the iterator protocol
>> but also offer a rich API including:
>>
>> - peek
>> - restart
>> - previous
>> - jump ahead (advance)
>>
>> all features that have been proposed, there is nothing stopping you from
>> adding those features to your iterator classes. But they all have
>> problems if considered to be necessary for *all* iterators.
>>
>> I would expect that, given a sufficiently compelling real-world
>> use-case, we would be prepared to add a jump ahead method to
>> list-iterators, as a specific feature of that iterator, not of all
>> iterators.
>>
>>
>> > A skip list which doesn't support O(1) random access but can advance
>> faster
>> > than naively calling next repeatedly
>> > A lazy infinite iterator which can efficiently calculate its state at
>> some
>> > future point  (e.g. `itertools.count`)
>>
>> What's your use case for advancing a count object, rather than just
>> creating a new one?
>>
>>     it = itertools.count()  # start at 0
>>     process(it)  # process some values
>>     it.advance(state)  # jump forward
>>     process(it)  # process some more values
>>
>> as opposed to what is already possible:
>>
>>     it = itertools.count()
>>     process(it)
>>     it = itertools.count(state)
>>     process(it)
>>
>> Real-world use-cases for this feature are far more useful than contrived
>> and artifical use-cases unlikely to ever occur in real code.
>>
>>
>> > My ladder two examples demonstrate that this could have utility outside
>> of
>> > sequences but for iterators in general.
>>
>> I'm sorry, I don't know what your ladder two examples are. Did you post
>> them in another thread?
>>
>>
>> --
>> Steve
>> _______________________________________________
>> Python-ideas mailing list -- python-ideas@python.org
>> To unsubscribe send an email to python-ideas-le...@python.org
>> https://mail.python.org/mailman3/lists/python-ideas.python.org/
>> Message archived at
>> https://mail.python.org/archives/list/python-ideas@python.org/message/I6PN73GZZ5K3L5Z4F6DQWOVHRZ2IMFMD/
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ZMCIDZPAGZTIWRHSVUDTDWTLQQ7YXJVW/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to