On Mon, Dec 09, 2019 at 10:19:43PM -0400, Juancarlo Añez wrote:

> And knowing that you must use *iter()* for 2-arg *next()* to (maybe) work
> right is idiosyncratic.

If you think that knowing to use `iter` before calling `next` is somehow 
advanced or difficult knowledge, I think that you have an exaggerated 
idea of the ineptitude of the average Python programmer.

Anyone who calls `next` directly on a list or other non-iterator will 
get a TypeError:

    TypeError: 'list' object is not an iterator

which makes it pretty obvious that the solution is to call `iter` first. 
I know absolute beginners won't read error messages, but that's a skill 
that people learn pretty quickly.


> It takes a "Python historian" to understand why it *may be correct* to use:
> 
> the_first_item_if_ordered = next(iter(container), default='not found')

What do you mean by "may be correct"? Can you give an example of when it 
isn't correct, assuming `container` is an iterable?


> While the semantics of *first()* (whichever the chosen implementation) are
> straightforward to explain:
> 
> 
> one_item_if_any = first(return_a_set(), default=-1)

I don't think it's more straightforward than the `next` version. There 
are at least two gotchas, or possibly two sides of the same gotcha, one 
minor and one (in my opinion) major.

The first is that, in a sense, the name `first` is misleading: it 
doesn't return the *first* item from an iterator, since the first item 
may be long gone; it returns the *next* item of an iterator.

If I have `letters = iter("abcde...z")` and have already advanced into 
the middle of the iterator, a naive user might expect that 

    first(letters)

will return "a" rather than whatever the next letter happens to be.

But the more serious gotcha is that `first` behaves very differently 
when called repeatedly on an iterator compared to other iterables.


> I agree with others in that the "*default*" argument should be explicit
> instead of implied. It's how *dict.get()*, and *dict.pop()*, etc., work.

When you say "explicit instead of implied", do you mean that there is no 
default value for the default?

If so, that's not how dict.get works:

    py> {}.get('some key') is None
    True



-- 
Steven
_______________________________________________
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/QWJALBOXOEYRS2OUIAUKHDLNMAPQTABO/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to