[Python-ideas] Retrying EAFP without DRY

Mike Meyer mwm at mired.org
Mon Jan 23 19:26:06 CET 2012

On Mon, 23 Jan 2012 15:07:01 +1000
Nick Coghlan <ncoghlan at gmail.com> wrote:

> On Mon, Jan 23, 2012 at 2:34 PM, Stephen J. Turnbull
> <stephen at xemacs.org> wrote:
> > Nick Coghlan writes:
> >  > On Mon, Jan 23, 2012 at 7:30 AM, Mike Meyer <mwm at mired.org>
> > wrote: > > or wrapping a loop around the code when it wasn't really
> > a loop. >
> >  > You want to do the same thing more than once: that's a loop.
> >
> > That's a question of point of view.  If "thing" is thought of as a
> > "try" (an operation that might fail), yes, he wants to do the same
> > thing a nondeterministic number of times, and in general, more than
> > once: it's a loop.  If "thing" is thought of as a "block" (which
> > isn't a try), then the "things" done with and without exception are
> > different: it's not a loop, it's a conditional.
> >
> > Looking at his example "superficially" (I intend no deprecation by
> > that word, just a point of view in looking at the code), I have some
> > sympathy for Mike's claim that "it's not a loop and it violates
> > DRY." I "know what he means" (and I bet you do, too!)  However,
> > when I try to define that, even informally, I arrive at the
> > paragraph above, and I end up coming down on the side that you
> > can't consistently claim that "it's not a loop" *and* claim that
> > "it violates DRY", in some deeper sense.
> Exactly - in a very real sense, "retry once" is just a special case of
> a more general looping pattern: you execute the body either once or
> twice, perhaps with some massaging of state between the two attempts.
> One way to write it is:
>     for attempt in (1, 2): # This iterable controls your number of
> attempts try:

I think that highlights why it's not really a loop. While "retry once"
is a general case of a looping pattern, it's *also* just a special
case of a more general exception handling pattern. Because it fits
under both special cases, it can be wrapped in a loop.

But *any* sequence of instructions can be wrapped in a loop. All you
need is a program counter (python is missing the tools to express it
really cleanly, so I'm pretending):

for pc in range(sys.maxsize):
    switch pc:
        0: first_block
	1: second_block
	2, 3: third_block
        4, 6: fourth_block
	5: fifth_block
	7: sixth_block
	   if not done:
	       pc -= 1
	else: break
    pc += 1

So what of this is a real loop? The third block is in a two-count
loop. The sixth block is in a while not done loop. The fourth block
corresponds to the case here - you want to rerun one bit of code with
another in the middle. You really don't want a general-purpose
loop. So having to write one doesn't express the intent correctly.

Of course, you can write a general-purpose loop this way. And there
are probably cases where such a loop is the intent. Which lowers the
value of a "retry" statement.


More information about the Python-ideas mailing list