There seems to be a growing list of issues with adding `itertools.first(x)` as shorthand for `next(iter(x))`:
* If `x` is an iterator, it modifies the iterator, which is counterintuitive from the name `first`.
* It'll still be difficult for new users to find/figure out.
In the end, I feel like the main case I want to use a `first` and `last` functions on are `dict`s; other objects like `range`, `str`, `list`, `tuple` all support `[0]` and `[-1]`.
So I wonder whether we should go back to this idea:
On Tue, 5 Oct 2021, Alex Waygood wrote:
[...] Another possibility I've been wondering about was whether several methods should be added to the dict interface:
- dict.first_key = lambda self: next(iter(self))
- dict.first_val = lambda self: next(iter(self.values()))
- dict.first_item = lambda self: next(iter(self.items()))
- dict.last_key = lambda self: next(reversed(self))
- dict.last_val = lambda self: next(reversed(self.values()))
- dict.last_item = lambda self: next(reversed(self.items()))
But I think I like a lot more the idea of adding general ways of doing these things to itertools.
At the least, I wonder whether a `dict.lastitem` method that's the nondestructive analog of `dict.popitem` would be good to add. This would solve the case of "I want an arbitrary item from this dict, I don't care which one, but I don't want to modify the dict so I'd rather not use popitem" which I've seen repeated a few times in this thread.
By contrast, I don't think `next(iter(my_dict))` is an intuitive way to solve this problem, even for many experts; and I don't think it's as efficient as `my_dict.lastitem()` would be, because the current `dict` code maintains a pointer to the last item but not to the first item.
[I also admit that I've mostly forgotten the original situation where I wanted this functionality. I believe it was an exhaustive search, where I wanted to branch on an arbitrary item of a dict, and nondestructively build new versions of that dict for recursive calls (instead of modifying before recursion and unmodifying afterward).]
One more idea to throw around: Consider the following "anonymous unpacking" syntax.
``` first, * = [1, 2, 3] *, last = [1, 2, 3] ```
For someone used to unpacking syntax, this seems like a natural extension to what we have now, and is far more flexible than just extracting the first element. The distinction from the existing methods (with e.g. `*_`) is that it wouldn't waste time extracting elements you don't want. And it could work well with things like `dict` (and `dict_items` etc.).
Erik