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/

Reply via email to