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
--
Erik Demaine  |  edema...@mit.edu  |  http://erikdemaine.org/
_______________________________________________
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/IQ2EJM5BTDEO4URUHN3XGR6XSXX22HFR/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to