To illustrate the distinction that someone (I think Steven D'Aprano) makes, I think these two (modestly tested, but could have flaws) implementations are both sensible for some purposes. Both are equally "obvious," yet they are different:
>>> import sys >>> from itertools import count >>> class map1(object): ... def __init__(self, fn, *seqs): ... try: # See if there is a length ... self._len = min(map(len, seqs)) ... except: # Fallback isn't in any sense accurate, just "large" ... self._len = sys.maxsize ... self._fn = fn ... self._seqs = seqs ... self._iters = [iter(seq) for seq in seqs] ... def __iter__(self): ... return self ... def __next__(self): ... args = [next(it) for it in self._iters] ... return self._fn(*args) ... def __len__(self): ... return self._len ... >>> class map2(map1): ... def __init__(self, fn, *seqs): ... super().__init__(fn, *seqs) ... def __next__(self): ... self._len -= 1 ... return super().__next__() ... >>> m1 = map1(add, [1,2,3,4], (5,6,7)) >>> len(m1) 3 >>> next(m1) 6 >>> len(m1) 3 >>> m2 = map2(add, [1,2,3,4], (5,6,7)) >>> len(m2) 3 >>> next(m2) 6 >>> len(m2) 2 >>> m1_inf = map1(lambda x: x, count()) >>> len(m1_inf) 9223372036854775807 >>> next(m1_inf) 0 >>> next(m1_inf) 1 I wasn't sure what to set self._len to where it doesn't make sense. I thought of None which makes len(mo) raise one exception, or -1 which makes len(mo) raise a different exception. I just choose an arbitrary "big" value in the above implementation. mo.__length_hint__() is a possibility, but that is specialized, not a way of providing a response to len(mo). I don't have to, but I do keep around mo._seqs as a handle to the underlying sequences. In concept those could be re-inspected for other properties as the user of the classes desired. On Sat, Dec 1, 2018 at 12:28 PM David Mertz <me...@gnosis.cx> wrote: > Other than being able to ask len(), are there any advantages to a slightly > less opaque map()? Getting the actual result of applying the function to > the element is necessarily either eager or lazy, you can't have both. > > On Sat, Dec 1, 2018, 12:24 PM Steven D'Aprano <st...@pearwood.info wrote: > >> On Sat, Dec 01, 2018 at 12:06:23PM -0500, David Mertz wrote: >> >> > Given that the anti-fix is just as simple and currently available, I >> don't >> > see why we'd want a change: >> > >> > # map->sequence >> > mo = list(mo) >> > >> > FWIW, I actually do write exactly that code fairly often, it's not hard. >> >> Sure, but that makes a copy of the original data and means you lose the >> benefit of map being lazy. >> >> Naturally we will always have the ability to call list and eagerly >> convert to a sequence, but these proposals are for a way of getting the >> advantages of sequence-like behaviour while still keeping the advantages >> of laziness. >> >> With iterators, the only way to get that advantage of laziness is >> to give up the ability to query length, random access to items, etc even >> when the underlying data is a sequence and that information would have >> been readily available. We can, at least sometimes, have the best of >> both worlds. Maybe. >> >> >> -- >> Steve >> _______________________________________________ >> Python-ideas mailing list >> Python-ideas@python.org >> https://mail.python.org/mailman/listinfo/python-ideas >> Code of Conduct: http://python.org/psf/codeofconduct/ >> > -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th.
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/