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