4 ms·
In reality most of these are really simple, the big question is how to handle end of iteration across iterators e.g. given zip(a, b) where a is shorter than b,
by masklinn 4y ago
In reality most of these are really simple, the big question is how to handle end of iteration across iterators e.g. given zip(a, b) where a is shorter than b, on the last iteration will b get updated or not?
- qsort 4y agoIn Python an iterator is simply an object that implements the __next__ method, and raises StopIteration to signal the end of the iteration. It's not hard to implement just about any protocol on top of that abstraction, e.g. you have itertools.zip_longest()
- masklinn 4y agoI know what an iterator is. I think you missed the point.
- qsort 4y agoWould you like to explain that further?
- masklinn 4y agoProgressing an iterator is a side-effect (a mutation). Depending how the last iteration is handled, zip(a, b) and zip(b, a) with iterators of different sizes can have different behaviours: if a is shorter than b, a naïve implementation would update b in the zip(b, a) case, but not in the zip(a, b) case.
- qsort 4y agozip is generally implemented as a functional concept, where the iterators take values from the backing iterable structure "by const &". You can implement a custom mutating zip operation on top of the iterator protocol.
- greenpeas 4y agoI believe masklinn is talking about whether `zip` consumes an extra element from the longer iterator on the last iteration, when the shorter iterator raises StopIteration. And the behavior might vary depending on the order of the arguments. def a(): yield "a1" def b(): yield "b1" yield "b2" x,y = a(),b() zip(x,y) # => [("a1","b1")] next(x) # => raise StopIteration next(y) # => "b2" x,y = a(),b() zip(y,x) # => [("b1","a1")] next(x) # => raise StopIteration next(y) # => raise StopIteration
- BiteCode_dev 4y agoThere is no unique solution to that problem since sometime you want consumption, and sometimes not, for one or more of the parameters. __builtins__.zip chose to consume iterators in the order they are passed as a parameter, and therefor end up with an assymetric consumption. That's why itertools.tee exists, so that we can chose case by case.
- Joker_vD 4y agoThat reminds me of a lovely paper "How to Add Laziness to a Strict Language Without Even Being Odd" by Wadler and MacQuenn. They use "map" as their running example, but the problem is basically the same.
- deleted 4y ago[deleted]
- lupire 4y agoThis is the problem with python's conflation of iterable and iterator, and maybe why so many programmers don't understand the difference when they pick up Java.
- masklinn 4y ago> This is the problem with python's conflation of iterable and iterator It really is not. It’s just a natural outcome of imperative langages. If operations can have side-effects, then combinator behaviour will affect those side-effects. You could do the same with iterables with side-effecting iterations. It’s also perfectly logical to be able to iterate an iterator.