The problem is that first() does not return the first item of the
iterator, but the *next item still available*.

   a = list('12345')
   b = iter('12345')

   first(a) == first(a)  # True
   first(b) == first(b)  # False

This is an excellent point, and something I hadn't considered. Unless someone can think of a good workaround that doesn't make the implementation hideously complex, I retract my support for adding `first()and `last()` to itertools.

On 10 Oct 2021, at 05:09, Steven D'Aprano <steve@pearwood.info> wrote:

On Wed, Oct 06, 2021 at 03:42:28PM +0100, Alex Waygood wrote:

Whether they are added to dict or itertools, there are still nine of
them

No, the suggestion was to add two functions to itertools (first() and
last(), which would work with any iterable, not just dicts), rather
than adding nine methods to the dict interface. This was precisely why
I was saying that I liked the itertools solution more.

Okay.

In another post, I've explained why I don't think that putting first()
in itertools would actually be useful (TL;DR: newbies wouldn't know it
was there, and to people experienced enough to know it was there, it's
likely easier to just use next() directly).

When I started writing this post, I was going to argue that we should
put first() and last() in itertools as recipes, for their pedagogical
value:

   def first(iterable):
       return next(iter(iterable))

   def last(iterable):
       return next(reversed(iterable))

I had got so far as to open bugs.python.org to create a ticket.

But I've convinced myself that they aren't even worthwhile as recipes.
The problem is that if we are being precise and accurate, and we should
be, the names are simply *wrong* and the behaviour will be confusing to
those we're supposedly trying to help.

The problem is that first() does not return the first item of the
iterator, but the *next item still available*.

   a = list('12345')
   b = iter('12345')

   first(a) == first(a)  # True
   first(b) == first(b)  # False

If that behaviour makes sense to you, and is what you expected, then
congratulations, you're probably a very sophisticated Pythonista who
understands that iterators mutate after each item is retrieved, in
which case you probably aren't going to get any benefit at all from a
named first() function.

But if you are one of those newbies who (we're told) need a named
function, then you will probably be totally gobsmacked that sometimes
first() will return the first item, and always the first item, and
sometimes it will return the first, second, third... items in sequence.

If we are to be precise and accurate, *sequences* have a first item, but
iterators only have a next item.



--
Steve
_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-leave@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/F6TG5EW3SKKMN6D6F7UBRRUNG2KYMMK5/
Code of Conduct: http://python.org/psf/codeofconduct/