statements in control structures (Re: Conditional Expressions don't solve the problem)

William Tanksley wtanksle at dolphin.openprojects.net
Fri Oct 26 02:37:15 CEST 2001


On Thu, 25 Oct 2001 01:17:31 +0000 (UTC), Huaiyu Zhu wrote:
>On Wed, 24 Oct 2001 20:11:31 GMT, William Tanksley
>>I'm confused -- I don't see how your version can work either.  Both of you
>>are iterating over an empty list, and the only code which could possibly
>>add anything to the list is inside the iteration; that list is empty no
>>matter what, so nothing will execute, and the list will never be anything
>>but empty.

>That's what that 'else' is for - and that's the whole point of this thread.
>I have a suspicion that the usage of for-else in Python is not well known to
>many discussants in this thread.

A well-founded suspicion.  I've complained about Python's for-else before,
and I find it so bad that I consider any code using it to be broken until
proven correct.  Looks like I accidentally followed that rule here (sorry,
my fault).

>The equivalent code is (note the duplication of primes.append(n)):
>    def getprimes(x):
>        primes = []
>        for n in range(2, x):
>            for p in primes:
>                if p*p > n:         primes.append(n); break
>                elif n % p == 0:    break
>            else:           primes.append(n)
>        return primes
>Try it and see how it works.

Yes, I see.  Thanks for the equivalent code.  I begin to see (thanks to
the equivalent code) the reasoning behind your 'for-while' construct: you
wish to have a way to automatically iterate through a sequence which has a
stopping point that has to be computed.  Such sequences will appear
especially often with generators (which can well be infinite).

I will join with those who suggest that you write this up in a PEP.

But it appears to me that generators, in addition to aggrivating the
problem, also provide the obvious solution:

def up_to_sqrt_of(square,sequence):
   for x in sequence:
     if x*x < square:
       yield x
     else: return

def primes(max):
   primes = []
   for n in range(2,max):
     for p in up_to_sqrt_of(n, primes):
       if n%p==0: break
     else: primes.append(n)

>>I don't like your "for x in list while y" construct, either.  It's
>>terrificly ambiguous: does it mean that every item in the list which meets
>>the 'y' criterion will be processed, or does it loop over all the items up
>>to the first one which fails to satisfy 'y'?

>So let me explain this in detail and hope I don't need to do it again.

I do appreciate your earlier explanation -- I now understand why you want
that code, and I see how it works.  I didn't find your explanation below
helpful.  It was confusing for two reasons: first, the way you laid it out
forced me to refer between three texts (the code, the explanation, and a
legend); and second, the legend referred to a "pass", which was not
present anywhere in the code.

But that's academic; as I mentioned, thanks to your other efforts, this
makes sense to me now.

>The pseudo code was:
>    def getprimes(x):
>        primes = []
>        for n in range(2, x):
>            for p in primes while p*p < n:
>                if n % p == 0: break
>            else: primes.append(n)
>        return primes
>The 'for p' loop will exit under three conditions:
>- p reaches end of primes: jump to (A)
>- not p*p < n: jump to (A)
>- n % p == 0: jump to (B)
>where 
>(A) primes.append(n)
>(B) pass

I'm not sure where (B) is.  Perhaps instead of "jump to (B)" your
explanation should say "continue the outer loop".

>The juicy part of the code is:
>            for p in primes while p*p < n:
>                if n % p == 0: break
>            else: primes.append(n)

>So the question is: is there a way to write the idea that two of the exits
>go to the same follow-up code (A) without actually duplicating the code in
>(A), or using a temporary variable to hold the state information?  I have
>not found a positive answer (which is not the same as claiming it does not
>exist).

Does the generator solution work for you?

>Why does this matter at all?

>I hope this clarifies what I meant when I said that the issue really appears
>to be the existence of two types of exits of loops.

Indeed.

>Of course, all of these could be easily done by using an auxiliary
>variable found_factor which is set to true or false before different
>breaks, and using an "if found_factor" after the loop.  But I found the
>pseudocode clearer, as long as one makes the mental distinction between
>"exiting due to exhausting of candidates" and "exiting due to a special
>condition being met".  It would be convenient if Python allows such
>pseudocodes to be real codes.

It really seems ideal for generators -- they form sequences which can have
arbitrary terminations, just like you want.  That way your real for loop
ALWAYS examines all of the possibilities.

>In any case, a syntax that removes the benefit of existing for-else and
>while-else structures would look quite a retrogress to me.

Grin.  Such a thing would lighten my heart -- I hate for-else.  Someday
I'll use it by accident, I'm afraid, and create code which is readable
only by Python experts.

>Huaiyu

-- 
-William "Billy" Tanksley



More information about the Python-list mailing list