[Andrew Barnert <abarnert@yahoo.com>]
Sure, but you can also explain first just fine by saying it returns the first thing in its argument, and that will stick as well.
We have different meanings for "fine" in this context. "The first thing in its argument" is English prose, and prone to misunderstanding. I'm absolutely fine with starting the docs that way, but not with letting it end there. It's too sloppy. There are (at least) two simple and rigorously, exhaustively correct ways to explain normal (iterable `it` not empty/exhausted) behavior. That a = first(it) binds `a` to the same object that for a in it: break would bind it to, or that a = next(iter(it)) would bind it to. The first way requires no knowledge of the `next` or `iter` builtins. I happen to use those a lot, because I often implement "general purpose" functions that operate _on_ iterables (along the lines of what most functions in `itertools` do). But I routinely see thousands of lines of Python code that never use them explicitly, not even once. I rarely see even dozens of lines of Python code that don't explicitly use `for`. For that reason I remain of the opinion that the former (`for`) way would be more accessible to more people. But both are useful explanations. Why you're so determined to fight against adding a brief, 100% true, explanation in the docs remains unclear to me.
This whole subthread is an attempt to come up with wording that solves a problem that I don’t think exists:
Writing good docs is always "a problem", in that it's not trivial. Newbies need an intuitive hint, experts may need 100% rigorously true and exhaustive specification.
Wes suggested everyone will be confused by using first on a set. I don’t think anyone will be. Do you disagree?
Again, nothing is obvious at first. I, again, aim at explanations that "stick": hard to forget _after_ they're learned.
If not, why do we need to solve that nonexistent confusion?
Well, why document first() at all? ;-)
... and they won’t be baffled by the fact that first on their set returns 2 either.
If only that were true, Stackoverflow could shut down ;-) ...
As above, I didn't really have newbies in mind. I did have the learning curve all Python programmers need to climb in mind. `next()` and `iter()` didn't even exist in earlier versions of Python, yet we somehow managed ;-)
Neither did itertools.
My point exactly ;-) first() can be - and "should be" - rigorously explained without reference to iter(), next(), or itertools.
And, just as with next and iter, you can go a long way in Python without learning itertools.
Nobody is asking anyone to learn itertools here. That just happens to be the most natural place for `first()` to live that anyone has suggested, and follows the prior art of the itertoolz and more-itertools packages. To _use_ it no more requires learning anything about itertools than, e.g., using fractions.gcd requires learning anything about fractions.Fraction. However, in that case, the fractions module was a weird place to put an advertised general-purpose integer function like gcd, so gcd eventually (3.5) moved to the math module (while it _really_ belongs in a doesn't-exist-yet imath module). Do you have a better suggestion for which namespace `first` should live in? There does, so far, appear to be consensus that it's not compelling enough to merit adding to the builtins.
... And by the time you get to looking for functions in itertools to use on a set, you’re not going to be baffled by the fact that a set’s order is just as arbitrary when used with itertools functions as it is with everything else.
I suppose it's possible someone will stumble into `first` by searching itertools for functions to use on a set, but I think this other way is much more likely: someone has a set, and asks a question (whether on a mailing list, an online forum, or to a colleague): "I want to get an element from the set, but not destructively. I've been doing `a = set.pop(); set.add(a)` but that code smells. Is there a better way?" "Sure! Do `a = itertools.first(set)` More, that way will work for any iterable object, although it will consume the next object from an iterator."
... I’m not all that irked, but it does annoy me a bit that it’s so easy for someone to derail a thread that’s making progress just by raising a spurious problem. People jump to trying to come up with the best solution without asking whether the problem actually needs to be solved.
Writing good docs doesn't happen by accident or magic, and I don't agree "returns the first thing in its argument" is _sufficient_ for "good docs". Thinking about the docs is also essential to making progress.