A single, general looping construct? (was: why no "do : until"?)

Alex Martelli aleaxit at yahoo.com
Fri Jan 5 11:23:46 EST 2001


"William Sonna" <wlsonna at attglobal.net> wrote in message
news:0O7zTzsxerl5-pn2-DVVVoFhFP1jH at bill...
> On Thu, 4 Jan 2001 11:07:39, "Alex Martelli" <aleaxit at yahoo.com>
> wrote:
>
> > "William Sonna" <wlsonna at attglobal.net> wrote in message
> > news:0O7zTzsxerl5-pn2-SISYKtwXTOmR at bill...
> >     [snip]
> > > Object Rexx's implementation of the generalized do is the best I've
> > > seen (in a real language, that is).  Works like this:
> >
> > Snipping: 5 different forms that _still_ don't cover the
Knuth-identified
> > general case of "N-and-1/2-times" loops.  We clearly have a very
> > different idea of what the word "best" means.
>
> My definition is easy, simple and obvious.  And Object Rexx's are
> simple, easy and obvious.  Python's while is simple, easy and obvious.
> Python's repeat until is simple, easy, but NOT OBVIOUS.

Five different languages constructs for a single task is not
'simple' -- it is 'multiple'.

> I find the N and 1/2 times to be totally loopy (pun intended).  Don't
> you?

No.  Knuth's article explaining it came out in 1974, and I started
programming right after that -- I also had the luck of a 'mentor'
who pointed me to suitable study materials, including that article
as soon as I was ready for it.  With a quarter century of familiarity
with the concept, of course I find it most natural.

Not being the kind of genius Knuth is, I guess I could not have come
up with this syntesis myself, but then, fortunately, I don't have
to: "seeing farther by standing upon the shoulders of giants", and
all that, you know.


> > Since when is it Pythonic to have many equivalent ways to express
> > one concept?
>
> Zero or more  of  something is not mathematically or logically the
> same as one or more.

But you capture both, and more besides, with "N or more for some N",
a more general concept.  That's a lot of what mathematics and logics
are about -- finding suitable abstractions, that will simplify your
mental toil through "just the right generalizations".


> So expressing "one or more" as "one plus zero or more" smacks of using
> "x^0" to express "one".

While expressing it as "N or more [for N=1]" is Pythonic (just one
concept, judiciously generalized, rather than a congeries of ad-hoc
constructs).

> You don't have to take my word for it......Go ask the re module if it
> knows the difference.

The re module's "sublanguage" is, of course, a completely
different one -- the (general case) {m,n} construct and the
(special cases) * and + constructs coexist, for example.  I
suspect historical reasons play a big part here.

> It does (thank GOD).  Otherwise [a,b,c]+ would have to be written as
> [a,b,c][a,b,c]+, which is generally accepted as bad style.

I'm not sure what role you think the repeated comma plays in
the '[a,b,c]' part (I would normally express it '[,abc]' if
I wanted to match either a comma or one of the first three
lowercase letters), but, anyway, the general form for "N or
more repetitions" of it would be "[,abc]{N,}".  Now, whether
N stands for 0 or 1 (or anything else), the style is equally
good.  I guess design considerations for a special-purpose
"little language" are different, particularly considering the
practical opportunity of just adopting a powerful (if obscure
and redundant) sublanguage that's already well-known.

> So what's the deal with Python?

It's a general-purpose programming language, with no need for
any special compatibility with existing ones.  Having a general
construct, introducing equivalent ones for several special
cases would be unPythonic.  (You'll hear no Pythonista claim
the re sublanguage is highly Pythonic, I'm sure -- particularly
since it's basically identical to the Perl sublanguage that
serves the same purpose:-).


> > > Fortran had even simpler control structures than Python, and was a
    [snip]
> > structures is "simpler than Python's"?!  Simple GOTO, assigned
> > GOTO, computed GOTO, logical IF, arithmetic IF, the DO statement...
    [snip]
> True, they were not easy to use.
>
> But at their core they were EXTREMELY simple concepts:  GOTO, IF, and
> DO.

The point is: they were NOT simple -- they were multiple.  There
was not 'one' way to GO TO, for example -- there were at least 4
(counting the arithmetic-if, which is a triple of GO TO's, with a
different keyword just to add more confusion).

> The variations you describe are grafted workarounds for the inherent
> limitations of a limited set of control structures.  Not unlike the
> loop construct we are discussing.

I agree on the 'not unlike': when you want five different
constructs to use for looping (and still don't cover the
simple generality of Knuth's single construct), there IS
a strong similarity to Fortran's use of 4+ ways to jump
around.  You're trying to compensate for lack of generality
by adopting multiplicity instead.

> I am of the opinion that control structures should state what they
> mean in the simplest possible terms.  One of the reasons I always
> hated Fortran.

Multiplicity becomes a real problem when you need to port or
otherwise maintain programs written by somebody so benighted
as to actually USE it -- if you have any sense, for your own
programs you'll settle on as small a subset as you can get
away with ("do the simplest thing that can possibly work").

E.g., "IF(X.ge.0)THEN//GOTO 100//ENDIF" even if you could say
that as "IF(X)110,100,100//110 CONTINUE", because the IF/THEN
construct is most general (the construct/statement distinction
is another finery that I _don't_ miss from Fortran...!-).

Of course, it's better NOT to have the needless multiplicity
of equivalent constructs in the language in the first place.


> [unprovoked anti-Perl advocacy snipped - PLEASE- I'm not here to
> troll]

I'm not impugning your purposes -- they may be as clean as
a mountain spring.  But, your ideas on language design
(multiplicity of equivalent expressions as desirable) _are_
more Perl-like than Python-like; thus, the 'unprovoked'
label is unwarranted.  You even choose as a presumably-good
example the re-sublanguage that Python took from Perl...!-)


> while 1:
>     yadda
>     yadda
>     if "whatever you think (should|should not) happen":
>         break
>
> Is clumsy and inconsistent compared to:
>
>     until "whatever you think (should|should not) happen":
>           yadda
>           yadda

It's not: it's just slightly-suboptimal syntax sugar
for the general structured loop-form.

> As for generalized while.......What would it really add?

Slightly better syntax sugar:

    loop:
        yadda
        yadda
    while "whatever"

for the test-at-end special case, with

    loop:
    while "whatever":
        yadda
        yadda

for the test-at-start more common case (some might
prefer to merge the first two lines as one here,
    loop while whatever:
but that's a different issue and I'm sticking to
the general form right now rather than debating
what variations it might include),

    loop:
        yadda
    while "whatever":
        more yaddas

for the general N-and-1/2 case.  The same two keywords
appear in every loop, with identical meaning: 'loop'
always denotes start-of-loop, 'while' always contains
the termination test -- and, most important, they're
indented at the same level (while the 'yadda's they
control are one indent to the rightwards), just like
other keyword pairs such as try/finally, if/else, &c.

Admitting a condition on the 'loop' line would be
a generalization (not really needed), as would having
more than one 'while' clause (like you can have
more than one 'elif' in an if/elif statement --
it's quite convenient to avoid needless nesting).

Python's syntax today is basically the fully
generalized form of this, with 'loop' always
carrying a condition (even if an always-on one,
which I think could be omitted) and spelled
'while', and each "while whatever:" spelled
"if not whatever: break" _and indented like the
code it controls rather than like the 'while'_.

*shrug* I'm OK with that syntax, even if it's not
quite the sugar I would like best (particularly
the indentation part).  I think the 'worst defect'
(and it's not that big!-) of the current syntax is
that it seems to promote threads about how Python
needs more special loop forms, when it clearly does
not, since it already has the general-loop (albeit
spelled peculiarly).  I guess that the cost of
rewriting all existing Python code, even if one
agreed with me that loop/while syntax is better,
would be higher than that of participating in these
threads (which one can choose to avoid:-).  Even
the mythical 'Py3K' to come, which will be free to
break some backwards compatibility, will no doubt
do so only when the gain from the incompatibility
is deemed larger than its cost -- it won't be
approached as a "greenfield" language design...:-).


Alex






More information about the Python-list mailing list