less awkward is:

some_iter = map(lambda x: x if print(x) else x, some_iter)

The tuple has a ~50% overhead, the case statement ~15%, compared to the
generator.

I think that the less awkward syntax solves the problem fine (if you can
come up with it). I like that it's explicit rather than requiring someone
to know what itertools.tap does.

On Sun, Oct 25, 2020 at 4:27 PM Samuel Freilich via Python-ideas <
python-ideas@python.org> wrote:

> This seems like it might be a reasonable thing to have in intertools? It's
> not hard to write this sort of thing with map:
>
> some_iter = map(lambda x: (print(x), x)[1], some_iter)
>
> But it's a little awkward. (Though maybe I'm missing a less awkward way to
> do that.)
>
> Java has Stream.peek for similar functionality, while Stream.forEach is
> analogous to Python's map.
>
> On Sun, Oct 25, 2020 at 9:02 AM <anderssonpub...@gmail.com> wrote:
>
>> Python has many tools for iteration, such as map and filter, that change
>> an iterator into another iterator without consuming the iterator. These
>> make it simple to deal with many items in a list without consuming
>> excessive memory.
>>
>> Occasionally it is useful to be able to tap into iterator items and
>> execute a function (such as a side effect to validate elements or print
>> them) without making any changes to the overall iterator. This is similar
>> to the idea of a tap in rxjs:
>> https://rxjs-dev.firebaseapp.com/api/operators/tap.
>>
>> The proposed interface would be:
>> def generate_items() -> list[int]:
>>     some_iter = range(10)
>>     some_iter = tap(assert_int, some_iter)
>>     some_iter = tap(print, some_iter)
>>     return list(some_iter)
>>
>> This would be useful to (for example):
>> 1. Debug chained iterators without a debugger (at the moment you would
>> have to convert the list and then print the whole list or include a print
>> statement in one of the chained functions)
>> 2. Check that items in an iterator conform to assumptions and raising
>> exceptions if they do not
>> 3. Improve type hints in editors since after the assert is executed all
>> items conform to the assert in the tap (for example, they are an integer)
>>
>> The implementation would be quite simple (at least in python):
>> def tap(func: typing.Callable[[T], typing.Any], iter: typing.Iterable[T])
>> -> typing.iterable[T]:
>>     for item in iter:
>>         func(item)
>>         yield item
>>
>> Thoughts?
>> _______________________________________________
>> 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/7Q3NR4SKUC72PVQ3APK2HL2HNX3HP2IE/
>> 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/7AUUGTM77ZJFJ4PSZUYHB2PW2VJKBYYT/
> 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/XJQMJU3PJ3AWOTB5MTGNHLNVAVIZG7K6/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to