[Python-Dev] For/while/if statements/comprehension/generator expressions unification
Hello, Well, we have "for", "while" and "if". We also have statements, list generator expressions and list comprehensions. In comprehensions we have the opportunity to use several for-s and in a same expression (for i in range (0, 640) for j in range (0, 640)), in loops we cannot; in comprehensions, we can use if-s to filter the items; in loops, we cannot, and we have to write an inner comparison instead. My opinion is that in so smart language as Python is, it would be great to have them generalized, so that the features available in list comprehensions should be available in statements, vice versa. All three statements (for/while/if) could be joined together into a single common one, where any of these could be combined and used multiple times (but for the cases when a "else"/"elif" etc causes are required, old-school one-statements should be left); and for such common expressions, they should be equal for both loop statements and list comprehensions/generator expressions. That is, the following loops should be possible: --- # This gives us some sugar to get rid of unnecessary indentations for x in range (0, 640) for y in range (0, 480): --- for x in range (0, 640) if should_handle_this_column(x) \ for y in range (0, 480) if should_handle_this_row(y): --- for nX, nY in ( f(x), f(y) for x in range (0, 640) if should_handle_this_column(x) for y in range (0, 480) if should_handle_this_row(y) ): --- for x in range (0, 640) for y in range (0, 480) while(!timeout()): --- for x in range (0, 640) while(!timeout_pos_in_row()) for y in range (0, 480) while(!timeout_rows()): --- # And the latest and the hugest one: for x in range (0, 640) if should_handle_this_column(x) while(!timeout_pos_in_row()) \ for y in range (0, 480) if should_handle_this_row(y) while(!timeout_rows() : --- # And almost the same as generator expression: for x, y in ( f(x), f(y) for x in range (0, 640) if should_handle_this_column(x) while(!timeout_pos_in_row()) for y in range (0, 480) if should_handle_this_row(y) while(!timeout_rows() ) --- Hope I didn't miss something important... -- With best regards, Alexander mailto:[EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] For/while/if statements/comprehension/generator expressions unification
Hello Josiah, JC> Alexander, JC> The essence of what you have proposed has been proposed (multiple times) before, JC> and I seem to remember it was shot down. To increase my understanding of Python-way, can you (or someone else) explain the reasons why such proposals were rejected? JC> The below functions offer the equivalent of list comprehensions with a JC> final post-processing step. Well, what I was suggesting is not just a cross of two lists but the syntax sugar which would make statements more consistent to the generators/comprehensions and also give some new opportunities. I think that my large proposal can be splitted to several almost-independent ones, each carrying separate features, able to be implemented independently and worth independent reconsidering: 1. Bring 'if'-s from generator/comprehension 'for' syntax to 'for' statement. That's truly inconsistent that one may write list2 = [i for i in list if cond(i)] but cannot write for i in list if cond(i): 2. Bring "several for-s in a row" ability from generators/comprehensions to the statement (and expand it to "several for-s and if-s", of course). We can write list2 = [f(i, j) for i in list1 for j in list2] but cannot write for i in list1 for j in list2: yield f(i, j) That looks inconsistent as well. Yes, for this little case we could do some kind of cross, but what if there are more loops, and/or some of them require filtering by if-s? 3. Bring 'while' into the loops, both statements and iterators. Now no need to worry about "hidden-goto" 'break', especially for the cases of nested loops, while it can be easily checked right inside the looping condition? Now we can easily do for i in largelist while !found: , isn't it nice and simple? -- С уважением, Alexander mailto:[EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Visibility scope for "for/while/if" statements
Hello, Don't want to be importunate annoyingly asking the things probably trivial for experienced community, but need to ask it anyway, after spending about two hours trying to find well-camouflaged error caused by it. Why the variables defined inside "for"/"while"/"if" statements (including loop variables for "for") are visible outside this scope? This litters the namespace, makes things more complex and requires even more attention from the programmer than even the uneasy C. Or makes him to watch for using each variable only once (prohibiting from using usual i/j/k variables); otherwise copypasting a piece of code can cause hardly-findable errors. But not even the variables from inside of statements are forgot in the outside namespace; what is most ridiculous is that the inner variables from a list comprehension are kept outside the comprehension! Yes, I am aware of one use case for this... er, feature. It could be useful to remember the last item of the loop after the loop is done... sometimes. But what is it for in other cases, except confusing the programmer? Or maybe can someone hint me whether I can somehow switch the behaviour on source-level to avoid keeping the variables outside the statements? Something like Perlish "import strict"? I couldn't find it myself. While global change of Python to the variables local to statements and list comprehension could definitely affect too much programs, adding it on a per-source level would keep the compatibility while making the life of Python programmers safer. Thanks in advance. Appendix 1: examples. cut here #!/usr/bin/env python -t a1 = ['a', 'b', 'c', 'd', 'e'] # Loop variable is alive outside the loop for k in a1: pass print "k: %s" % k # Loop variable is alive even outside the list comprehension! b1 = [l for l in a1] print "l: %s" % l # If there are several loops in a comprehension, # variables from all of them are kept intact c1 = [(m, n) for m in a1 for n in b1] print "m: %s, n: %s" % (m, n) # Loop variable is kept even from nested comprehensions d1 = [o for o in [p for p in a1]] print "o: %s, p: %s" % (o, p) # And the winner is... for r in a1: print "r0: %s, " % r, e1 = [r for r in b1] # Now try to access the "r" variable from the loop! print "r1: %s" % r cut here -- With best regards, Alexander mailto:[EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Visibility scope for "for/while/if" statements
Hello Josiah, >> Why the variables defined inside "for"/"while"/"if" statements >> (including loop variables for "for") are visible outside this scope? JC> if and while statements don't define variables, so they can't expose JC> them later in the scope. They don't. They just leak internal ones: i = 0 while i != 1: i += 1 j = 5 print j JC> In regards to 'for' loops, they have always done that, there is code JC> that relies on that behavior, and changing behavior would unnecessarily JC> break code. I mentioned it below: while unconditional changing the behaviour will definitely break a lot, something like "import strict" would help those ones who rate such behaviour enough error-prone to reconsider proceeding using Python at all. JC> Further, you should clarify what you would want this mythical non-leaky JC> for loop to do in various cases. What would happen in the following JC> case? JC> i = None JC> for i in ...: JC> ... JC> print i JC> ... assuming that the loop executed more than once? Would you always JC> get 'None' printed, or would you get the content of the last variable? As for me (if my humble opinion is useful for you), the best would be to 1. assume that a loop variable is always newly-declared for this loop, 2. all variables first declared inside the loop are local to this loop. Thus, your example falls to case 1: "i" variable is newly declared for this loop. Well, we don't reuse old value of i to start the iteration from a particular place, like below? i = 5 for i in [3,4,5,6,7]: print i, More general, the variables could be assumed local only to the *same or higher* indentation level. JC> What about: JC> x = None JC> for i in ...: JC> x = f(i) JC> ... JC> print x JC> Would 'x' be kept after the loop finished executing? case 2: "x" variable is declared already. And if there is no "x = None" line, it should tell "name 'x' is not defined". Unless we are prone to funny "uncertainly defined" cases, if some variable is defined inside an "in" in the loop. JC> I would imagine in your current code you are running something like JC> this: JC> i = #some important value JC> ... #many lines of code JC> for i in ...: JC> ... JC> #you access the 'i' you bound a long time ago JC> In this case, you are making a common new programmer mistake by using JC> the same variable name for two disparate concepts. Nah, here is my error-case: I made several loops, one by one, using the "i" variable for looping. Then in the latest loop I changed the "i" name to more meaningful "imsi" name in the "for" declaration and whenever I found inside the loop. As I use "i" name *for loops exclusively*, I didn't wittingly reuse the same name for different purposes. The problem was that I missed one occurance of "i" variable inside the loop code, so it gained the same value (from the completion of previous loop) throughout all the "imsi" loop. And the interpreter didn't notice me that "I am using the undefined variable" (since it is considered defined in Python), as accustomed from other languages. That's my sorrowful story. JC> If the 'i' that was JC> initially bound was important through the lifetime of the scope, you JC> should have named it differently than the 'i' that was merely a loop JC> variable. I'm pretty happy that I didn't ever made a list comprehension with "i" variable inside the loop over "i" variable. While I wasn't aware of these side-effects, it would be even harder spottable. Now I'll look more carefully at copy-pasting list comprehensions, in every case examining all of the lower-indent variables for not to clash. JC> I will also point out that in general, not leaking/exposing/etc. such JC> variables would necessarily slow down Python. Why? I agree, this is one of obvious advantages of absence of pseudo-namespaces (wasting the resources to allocation and removal of variables, etc). Though in case of presence of pseudo-namespaces, it an easily be emulated by initializing the variable first-time on the highest-level of indentation. But for the "performance-oriented/human-friendliness" factor, Python is anyway not a rival to C and similar lowlevellers. C has pseudo-namespaces, though. JC> Python semantics seem to have been following the rule of "we are all JC> adults here". I always believed that the programming language (as any computer program) should slave to the human, rather than a human should slave to the program. JC> Generally though, Python follows a common C semantic of variable leakage. JC> C Code: JC> int i; // required in some versions of C JC> for (i=0;i<10;i++) { JC> ... JC> } "for (int i = 0; i < 10; i++)" works fine nowadays. JC> Again: test your assumptions. If your untested assumptions are wrong, JC> don't complain that the language is broken. In my case, as I explained already, it was not a assumption but an uncatched mistype, which is usually catched in other languages d
Re: [Python-Dev] Visibility scope for "for/while/if" statements
Hello Josiah, >> i = 0 >> while i != 1: >> i += 1 >> j = 5 >> print j JC> Maybe you don't realize this, but C's while also 'leaks' internal JC> variables... JC> int i = 0, j; JC> while (i != 1) { JC> i++; JC> j = 5; JC> } JC> printf("%i %i\n", i, j); Yeah, it may *leak* it in your example. But the advantage is that it may *not leak* as well: for (int i = 0; i <= 5; i++) { int j = 5; } printf ("%i\n", j); // Won't be even compiled Or in our "while" case: int i = 0; while (i != 1) { i++; int j = 5; } printf("%i %i\n", i, j); JC> If you haven't yet found a good use for such 'leakage', you should spend JC> more time programming and less time talking; you would find (quite JC> readily) that such 'leaking' is quite beneficial. I see such usages and realize the possible gains from it. But for about five years of software development in a bunch of programming languages, I've found good uses of non-leaking variables *as well*. Up to the level of manually "enclosing" the temporary variables used only once: ... int i = input(); int result; { int j = f1(i); int k = f2(i, j); result = f3(i, j, k); } // Now j and k are dead ... >> accustomed from other languages. That's my sorrowful story. JC> So you mistyped something. I'm crying for you, really I am. Yeah, I did. Just forgot removing the usage / renaming of variable neved initialized (I thought) before. And my error was that I relied upon the interpreter to catch it, mistakenly assuming the locality of variables inside loops as a consistency with other common languages. Mea culpa, without any jeers. The only reason why I was wrote my email was to get the understanding of community assessment of such behaviour, and/or probable workarounds. No blame against Python - it's great even with this unusualty. >> But for the "performance-oriented/human-friendliness" factor, Python >> is anyway not a rival to C and similar lowlevellers. C has >> pseudo-namespaces, though. JC> C does not have pseudo-namespaces or variable encapsulation in for loops. Neither for (int i = 0; i <= 5; i++) { int j = 5; } printf ("%i\n", i); nor for (int i = 0; i <= 5; i++) { int j = 5; } printf ("%i\n", j); gets compiled though with "gcc -std=c99". That is, each loop introduces a new scoping level. JC> Ah hah hah! Look ladies and gentlemen, I caught myself a troll! Python JC> does not rival C in the performance/friendliness realm? Who are you JC> trying to kid? There is a reason why high school teachers are teaching JC> kids Python instead of Pascal, Java, etc., it's because it is easier to JC> learn and use. Ohh, my slip made me considered a troll... I meant only that Python does not rival C in such area as "performance by all means, even with decrease of friendliness" (but the overall performance is indeed good, I've seen even the VoIP solution written purely on on Python). And I believe noone of Python developers want it to be rival. JC> What you are proposing both would reduce speed and JC> usability, which suggests that it wasn't a good idea in the first place. Yes, it lacks performance, but I still believe that an opportunity to close the visibility of variables (*opportunity* rather than *behaviour change*!) is better in terms of "friendliness" rather than lack of it. Just because it offers the alternatives. Because C-style closed visibility can emulate the variable lack, but not vice versa. At least one voice here (of Gareth McCaughan) is not-strictly-against it. So I cannot agree that such *option* can reduce usability. >> "for (int i = 0; i < 10; i++)" works fine nowadays. JC> I'm sorry, but you are wrong. The C99 spec states that you must define JC> the type of i before using it in the loop. Maybe you are thinking of JC> C++, which allows such things. "gcc -std=c99" compiles the line "for (int i = 0; i <= 5; i++);" perfectly. Along with another sample mentioned above . To this day, I relied upon gcc in terms of standards compatibility... JC> Tes your ideas on comp.lang.python first, when more than a handful of JC> people agree with you, come back. Ok. Next time I shall be more careful. Sorry again, and thanks for your time. And thanks for more-or-less patient answers. -- With best regards, Alexander mailto:[EMAIL PROTECTED] ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com