
On Sat, Aug 1, 2020 at 3:50 PM Steven D'Aprano <steve@pearwood.info> wrote:
On Sat, Aug 01, 2020 at 02:08:08PM +1000, Chris Angelico wrote:
On Sat, Aug 1, 2020 at 1:43 PM Steven D'Aprano <steve@pearwood.info> wrote:
Some years ago, someone (I think it was Nick Coghlan?) proposed a standard solution for this issue, a context manager + decorator function that guarded against a specific exception. Nothing much came of it, but I did experiment with the idea, and got something which you could use like this:
with exception_guard(StopIteration): first = next(iter(mydict.items()))
My understanding of this is that 'first' is unassigned if StopIteration happens.
Sorry for not being more explicit about what was going on. I was stuck in my own head and didn't consider that others might not recall the discussion from all those many years ago, mea culpa.
The exception guard doesn't merely catch and discard exceptions. It re-raises with a new exception, RuntimeError by default.
or like this:
safenext = exception_guard(StopIteration)(next) first = safenext(iter(mydict.items()))
My understanding of this is that I am confused. What does safenext return?
Nothing; it raises RuntimeError.
Ahh, okay. So it's safe in the sense that it can't accidentally leak a confusing exception. Unfortunately a lot of people are going to assume that it means "will always give a useful return value". Definitely worth being very very clear about the semantics. And it's really not the ideal semantics here anyway. What you actually want is ValueError if the dict is empty. There's no easy way to spell that generically, so it'd want a helper function, which means it would probably do well as a method. ChrisA