Re: while expression feature proposal
On 10/26/12 19:18, Steven D'Aprano wrote: def iterate_until_none_or_false(func, *args, **kwargs): while True: x = func(*args, **kwargs) # Halt if x is None or False, but not other falsey values. if x is None or x is False: return yield x for x in iterate_until_none_or_false( some_function, 1, 2, c, spam=yummy): process(x) I was initially a pretty strong advocate of the proposed as syntax. However, the more I've thought about it, the more I keep coming back to how I've solved the problem in the past which is mostly what Steven suggests here. There are so many edge-cases and warts in the as syntax; most of which disappear with this generator+forloop: - yielding/unpacking multiple results each time: the as syntax would get really ugly. Do you test the whole result, or an element of the result? - knowing the stopping condition varies: is it when something is False-ish (an empty string/tuple/list, False, None, etc)? When it is None? When it is exactly False? - the whole x = (foo(bar) as result) if result else None (or should that be x = result if (foo(bar) as result) else None?) style/discussion just really looks ugly to me. Usually I find Python code quite beautiful and this syntax doesn't resonate as beautiful. To despite my previous excitement, I'm now neutral at best on a limited while TERM as VAR: syntax. I know this being persuaded by rational arguments and changing one's mind thing is rare on the Intarwebs, so I hope I haven't upset the natural balance of things too greatly. :-) -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Dan Loewenherz dloewenh...@gmail.com writes: In this case, profile_id is None when the loop breaks. It would be much more straightforward (and more Pythonic, IMO), to write: client = StrictRedis() while client.spop(profile_ids) as profile_id: print profile_id That is pretty loose, in my opinion. If the loop is supposed to return a string until breaking on None, the break test should explicitly check for None rather than rely on an implicit bool conversion that will also test as false on an empty string. Code that handles strings should do the right thing with the empty string. What you posted relies on an unstated assumption that the strings that come back are never empty. it's a net negative from just doing things the canonical way (with the while / assignment pattern). Yeah, the while/assignment is a bit ugly but it doesn't come up often enough to be a bad problem, imho. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 5:06 PM, Paul Rubin no.email@nospam.invalid wrote: Dan Loewenherz dloewenh...@gmail.com writes: In this case, profile_id is None when the loop breaks. It would be much more straightforward (and more Pythonic, IMO), to write: client = StrictRedis() while client.spop(profile_ids) as profile_id: print profile_id That is pretty loose, in my opinion. If the loop is supposed to return a string until breaking on None, the break test should explicitly check for None rather than rely on an implicit bool conversion that will also test as false on an empty string. while (client.spop(profile_ids) as profile_id) is not None: print profile_id Why is everyone skirting around C-style assignment expressions as though they're simultaneously anathema and the goal? :) But seriously, this new syntax would probably enhance Python somewhat, but you're going to end up with odd edge cases where it's just as almost-there as current syntax is for what this will solve. Is it worth doing half the job? ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, 26 Oct 2012 17:23:12 +1100, Chris Angelico wrote: Why is everyone skirting around C-style assignment expressions as though they're simultaneously anathema and the goal? :) Only if your goal is to introduce an anathema :P -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thursday, October 25, 2012 11:06:01 PM UTC-7, Paul Rubin wrote: Dan Loewenherz dloewenh...@gmail.com writes: In this case, profile_id is None when the loop breaks. It would be much more straightforward (and more Pythonic, IMO), to write: client = StrictRedis() while client.spop(profile_ids) as profile_id: print profile_id That is pretty loose, in my opinion. If the loop is supposed to return a string until breaking on None, the break test should explicitly check for None rather than rely on an implicit bool conversion that will also test as false on an empty string. Code that handles strings should do the right thing with the empty string. What you posted relies on an unstated assumption that the strings that come back are never empty. I think this is a good point. However, I can't think of any situation where I'd want to work with an empty string (in the applications I've worked with, at least). We also don't special case things like this just because x is an empty string. If this while EXPR as VAR thing were to move forward, we shouldn't treat the truth testing any differently than how we already do. IMO we should write our applications with the understanding that '' will return False and work with that. Here's a workaround BTW. Just have that method return a tuple, and do the truth testing yourself if you feel it's necessary. while client.spop(profile_ids) as truthy, profile_id: if not truthy: break print profile_id Here, client.spop returns a tuple, which will always returns true. We then extract the first element and run a truth test on it. The function we use is in charge of determining the truthiness. Dan -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 9:29 AM, Dan Loewenherz dloewenh...@gmail.com wrote: while client.spop(profile_ids) as truthy, profile_id: if not truthy: break print profile_id Here, client.spop returns a tuple, which will always returns true. We then extract the first element and run a truth test on it. The function we use is in charge of determining the truthiness. I don't like the idea of testing the first element. There's a large element of surprise in doing that, I think. I would expect the truth test to be the same with or without the existence of the as clause there. That is, you should be able to remove the as clause and have exactly the same behavior, just without the assignments. So it would need to test the entire tuple. That brings up an interesting additional question in my mind, though. Should the while loop syntax attempt to perform the assignment on the very last test, when the expression is false? I think there is a good argument for doing so, as it will allow additional inspection of the false value, if necessary. In the above, though, if the return value is false (an empty tuple or None) then the assignment would fail during unpacking, raising an exception. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Dan Loewenherz dloewenh...@gmail.com writes: We also don't special case things like this just because x is an empty string. If this while EXPR as VAR thing were to move forward, we shouldn't treat the truth testing any differently than how we already do. IMO we should write our applications with the understanding that '' will return False and work with that. We don't already treat the truth testing any particular way because we don't have this construction in the language at the moment. However, it's well-established in Python that converting a string to a bool results in False iff the string is empty. The empty string is a perfectly good string and code that deals with strings should handle the empty string properly, unless it knows the string won't be empty. Basic modularity principles say to avoid putting such knowledge into more of the code than necessary. The conclusion is to not automatically convert the parameter to a bool. However, if the as can be part of an expression as in Chris Angelico's post, Chris's suggestion while (client.spop(profile_ids) as profile_id) is not None: print profile_id looks good to me. while client.spop(profile_ids) as truthy, profile_id: if not truthy: break This is ugly on two levels. First of all, if the .spop() still returns None at the end of the input, the tuple unpacking will fail. Second, the separate test and break defeats the purpose of the while ... as construction. Might as well use the current style of assignment and test inside the loop. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 26Oct2012 09:10, Paul Rubin no.email@nospam.invalid wrote: | However, if the as can be part of an expression as in Chris Angelico's | post, Chris's suggestion | | while (client.spop(profile_ids) as profile_id) is not None: | print profile_id | | looks good to me. Now this pulls me from a -0 to a +0.5. Instead of burdening the control constructs with further structure, make as a binding operation for keeping intermediate results from expressions. It will work anywhere an expression is allowed, and superficially doesn't break stuff that exists if as has the lowest precedence. Any doco would need to make it clear that no order of operation is implied, so that this: x = 1 y = (2 as x) + x does not have a defined answer; might be 2, might be 3. Just like any other function call with side effects. Speaking for myself (of course!), I definitely prefer this to adding as as a post expression struction on if/while/etc. I'm not +1 because to my mind it still presents a way for assignment/binding to not be glaringly obvious at the left hand side of an expression. It would probably mean folding the except/with as uses back into expressions and out of the control-structural part of the grammar. I can't see that that would actually break any existing code though - anyone else? Cheers, -- Cameron Simpson c...@zip.com.au UNIX was not designed to stop you from doing stupid things, because that would also stop you from doing clever things. - Doug Gwyn -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 4:03 PM, Cameron Simpson c...@zip.com.au wrote: It will work anywhere an expression is allowed, and superficially doesn't break stuff that exists if as has the lowest precedence. Please, no. There is no need for it outside of while expressions, and anywhere else it's just going to be bad practice. Even if it's considered an expression, let's only allow it in while expressions. Any doco would need to make it clear that no order of operation is implied, so that this: x = 1 y = (2 as x) + x does not have a defined answer; might be 2, might be 3. Just like any other function call with side effects. Actually, the docs are clear that expressions are evaluated left to right, so the expected result of the above would be 4. It would probably mean folding the except/with as uses back into expressions and out of the control-structural part of the grammar. I can't see that that would actually break any existing code though - anyone else? Yes it would, because the meaning is a bit different in both of those cases. For except, the result of the expression (an exception class or tuple of classes) is not stored in the target; the exception *instance* is. Similarly for with, the result of the expression is not stored; the result of calling its __enter__ method is, which is often but not always the same thing. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 1:12 AM, Dan Loewenherz dloewenh...@gmail.com wrote: It seems the topic of this thread has changed drastically from the original message. 1) while EXPR as VAR in no way says that EXPR must be a boolean value. In fact, a use case I've run into commonly in web development is popping from a redis set. E.g. client = StrictRedis() while True: profile_id = client.spop(profile_ids) if not profile_id: break print profile_id In this case, profile_id is None when the loop breaks. It would be much more straightforward (and more Pythonic, IMO), to write: client = StrictRedis() while client.spop(profile_ids) as profile_id: print profile_id For loops are pythonic. You can do this in Python today: client = StrictRedis() for profile_id in iter(lambda: client.spop(profile_ids), None): pass I would like a better iter(), rather than a better while loop. It is irritating to pass in functions that take arguments, and it is impossible to, say, pass in functions that should stop being iterated over when they return _either_ a None or a, say, False. -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 2:23 AM, Chris Angelico ros...@gmail.com wrote: while (client.spop(profile_ids) as profile_id) is not None: print profile_id Why is everyone skirting around C-style assignment expressions as though they're simultaneously anathema and the goal? :) Why should these two statements behave differently? :( with foo() as bar: bar.baz() with (foo() as bar): bar.baz() I don't understand why everyone is so attached to this as syntax. It's confusing because it behaves subtly differently than how it works in with, and it puts the variable on the wrong side of the assignment operator. (I've always been partial to :=, personally.) -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 10/26/12 17:03, Cameron Simpson wrote: On 26Oct2012 09:10, Paul Rubin no.email@nospam.invalid wrote: | while (client.spop(profile_ids) as profile_id) is not None: Now this pulls me from a -0 to a +0.5. Any doco would need to make it clear that no order of operation is implied, so that this: x = 1 y = (2 as x) + x does not have a defined answer; might be 2, might be 3. Just like any other function call with side effects. I really don't like undefined (or underdefined) specs. If it was to be PEP'd out, I'd want to address as many edge cases as possible. Such as y = (2 as x) + (3 as x) + (4 as x) y = (2 as x) + 4 as x y = booleanish and (2 as x) or (4 as x) y = booleanish and 2 or 4 as x y = (2 as x) if booleanish else (3 as x) y = (2 as x) if booleanish else (3 as z) regardless of how $PEJORATIVE, that's a dumb thing to do! it is. I hate C for how underdefined a lot of corners are. (amongst my hatreds of C are such diverse elements as: underdefined corners, a pitiful standard library, the ease of shooting yourself in the foot, ...) I'm not +1 because to my mind it still presents a way for assignment/binding to not be glaringly obvious at the left hand side of an expression. I think this is why I like it in the while (and could be twisted into accepting it for if) because it also introduces an implied/actual scope for which the variable is intended. In an arbitrary evaluation/assignment, it's much easier to lose the definition nature of it at the top of a block. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 4:12 PM, Devin Jeanpierre jeanpierr...@gmail.comwrote: For loops are pythonic. You can do this in Python today: client = StrictRedis() for profile_id in iter(lambda: client.spop(profile_ids), None): pass I would like a better iter(), rather than a better while loop. It is irritating to pass in functions that take arguments, and it is impossible to, say, pass in functions that should stop being iterated over when they return _either_ a None or a, say, False. You can kind of do this by creating a class implementing __eq__ and passing that in as the sentinal to the iter method. class FlexibleEquality(object): def __init__(self, *candidates): self.candidates = candidates def __eq__(self, other): return any(other == candidate for candidate in self.candidates) client = StrictRedis() for profile_id in iter(lambda: client.spop(profile_ids), FlexibleEquality(False, None)): pass But this is yucky. I'd much rather have something a bit more clear to the reader. The above is somewhat convoluted. I would far prefer for while EXPR as VAR to run through the results of EXPR as an iterable and continue the loop if any of the values in the iterable is truthy, maybe passing only the first value of the iterable to VAR. Gives maximum flexibility with the cleanest resulting code. client.spop(profile_ids) # conditional succeeds, '123' passed to profile_id '123', True client.spop(profile_ids) # conditional succeeds, '' passed to profile_id '', True client.spop(profile_ids) # conditional fails '', False Dan -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 6:03 PM, Cameron Simpson c...@zip.com.au wrote: Any doco would need to make it clear that no order of operation is implied, so that this: x = 1 y = (2 as x) + x does not have a defined answer; might be 2, might be 3. Just like any other function call with side effects. But function calls with side effects _do_ have a defined order of evaluation. Left to right. And the answer should be 4. http://docs.python.org/reference/expressions.html#evaluation-order def set_(d, k, v): ... d[k] = v ... return v ... d = {} set_(d, 'x', 1) 1 set_(d, 'y', set_(d, 'x', 2) + d['x']) 4 -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 26Oct2012 19:41, Devin Jeanpierre jeanpierr...@gmail.com wrote: | On Fri, Oct 26, 2012 at 6:03 PM, Cameron Simpson c...@zip.com.au wrote: | Any doco would need to make it clear that no order of operation is | implied, so that this: | |x = 1 |y = (2 as x) + x | | does not have a defined answer; might be 2, might be 3. Just like any | other function call with side effects. | | But function calls with side effects _do_ have a defined order of | evaluation. Left to right. | And the answer should be 4. | http://docs.python.org/reference/expressions.html#evaluation-order No. Separate _expressions_ are evaluated left to right. So this: f(1), f(2) calls f(1) first, then f(2). But this: f(1) + f(2) need not do so. Counter-documentation welcomed, but the doco you cite does not define an order for the second example above. | | def set_(d, k, v): | ... d[k] = v | ... return v | ... | d = {} | set_(d, 'x', 1) | 1 | set_(d, 'y', set_(d, 'x', 2) + d['x']) | 4 That may just be a coincidence of implementation - there's no special reason to change the evaluation order form the lexical order there, but expression optimisers should have a free hand generally. Cheers, -- Cameron Simpson c...@zip.com.au Acceptance Testing: Dropping your mods straight into the production environment to see if the users will accept them. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 7:41 PM, Dan Loewenherz dloewenh...@gmail.com wrote: -- snip insanity -- But this is yucky. I'd much rather have something a bit more clear to the reader. That's why I said I wanted a better iter, not some equality-overriding object strawman thing. I was thinking more like this: for profile_id in iter(None)(client.spop, profile_ids): or alternatively: for profile_id in iter(bool)(client.spop, profile_ids): Or perhaps either as keyword arguments (which is the only reason I curried iter). The interesting case for in-place assignment is not here. This is a trivial case. It's in cases like this: while True: x = foo(bar()) if x is None: break if x % 2 == 0: break print x Imagine doing that with iter. :) -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 7:56 PM, Cameron Simpson c...@zip.com.au wrote: No. Separate _expressions_ are evaluated left to right. So this: f(1), f(2) calls f(1) first, then f(2). But this: f(1) + f(2) need not do so. Counter-documentation welcomed, but the doco you cite does not define an order for the second example above. Actually, it does. Both f(1) and f(2) are separate (sub-)expressions in f(1) + f(2). More to the point, it gives the following example: In the following lines, expressions will be evaluated in the arithmetic order of their suffixes: ... expr1 + expr2 * (expr3 - expr4) I sympathize with your concern, though. Order of evaluation is very bitey, and it's better to be safe than sorry. -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 26Oct2012 18:26, Tim Chase s...@thechases.com wrote: | On 10/26/12 17:03, Cameron Simpson wrote: | On 26Oct2012 09:10, Paul Rubin no.email@nospam.invalid wrote: | | while (client.spop(profile_ids) as profile_id) is not None: | | Now this pulls me from a -0 to a +0.5. | | Any doco would need to make it clear that no order of operation is | implied, so that this: | |x = 1 |y = (2 as x) + x | | does not have a defined answer; might be 2, might be 3. Just like any | other function call with side effects. | | I really don't like undefined (or underdefined) specs. If it was to | be PEP'd out, I'd want to address as many edge cases as possible. I would not. Big time. One of the reasons C is so successful as a lower level language is that by defining only what is needed to be defined to make it _possible_ to get predictable and useful behaviour, maximum flexibility is left for implementation to adapt to particular environments as freely as possible. Pinning down all the corner cases is in general a bad idea, IMO. Every corner case you pin down is an early decision for inflexibility that may later prove to be illfounded. Specify what _needs_ to be specified to achieve the required effect. And stay the hell away from things that only constraint outcomes while not providing the required effect. To take an obvious counter example: your stance would encourage defining the iteration order of dictionary keys. To no good purpose, merely to present definition of _all_ operations instead of just the necessary operations. | Such as | y = (2 as x) + (3 as x) + (4 as x) | y = (2 as x) + 4 as x I would want these to be ambiguous, myself. | y = booleanish and (2 as x) or (4 as x) | y = booleanish and 2 or 4 as x | y = (2 as x) if booleanish else (3 as x) | y = (2 as x) if booleanish else (3 as z) None of these is ambiguous. The second one could be harder to read and want some brackets purely for clarity, but it is perfectly well defined in outcome already. | regardless of how $PEJORATIVE, that's a dumb thing to do! it is. No, sometimes dumb things should remain bad ideas. Defining them to all just makes them no longer obviously bad ideas, merely subtly bad ideas. And subtly bad ideas are worse! | I hate C for how underdefined a lot of corners are. (amongst my | hatreds of C are such diverse elements as: underdefined corners, a | pitiful standard library, the ease of shooting yourself in the foot, | ...) The C standard library was pretty good for when it came out. And the higher up the available facilities tree you go the more choices there are about how something should be done. C is still one of my favourite languages in its domain, though I haven't used it much for several years. If you're uncomfortable with C, try to stay away from it. (I try to stay away from C++ and its bretheren for similar reasons.) | I'm not +1 because to my mind it still presents a way for | assignment/binding to not be glaringly obvious at the left hand side of | an expression. | | I think this is why I like it in the while (and could be twisted | into accepting it for if) because it also introduces an | implied/actual scope for which the variable is intended. A conceptual scope, sure. Presumably not a real one in Python... | In an | arbitrary evaluation/assignment, it's much easier to lose the | definition nature of it at the top of a block. I'm not sure I agree here. Code example? Cheers, -- Cameron Simpson c...@zip.com.au Everything should be made as simple as possible, but no simpler. - Albert Einstein -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 27Oct2012 10:56, I wrote: | On 26Oct2012 19:41, Devin Jeanpierre jeanpierr...@gmail.com wrote: | | But function calls with side effects _do_ have a defined order of | | evaluation. Left to right. | | And the answer should be 4. | | http://docs.python.org/reference/expressions.html#evaluation-order | | No. Separate _expressions_ are evaluated left to right. [...] | need not do so. Counter-documentation welcomed, but the doco you cite | does not define an order for the second example above. [...] On 26Oct2012 16:48, Ian Kelly ian.g.ke...@gmail.com wrote: | does not have a defined answer; might be 2, might be 3. Just like any | other function call with side effects. | Actually, the docs are clear that expressions are evaluated left to | right, so the expected result of the above would be 4. Ian, Devin, my apologies. You're right, the docs are clear and my brain is foggy. So, no ambiguity about that with the suggested as operator. -- Cameron Simpson c...@zip.com.au Well, if you didn't struggle so much, you wouldn't get rope burns. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 26Oct2012 16:48, Ian Kelly ian.g.ke...@gmail.com wrote: | On Fri, Oct 26, 2012 at 4:03 PM, Cameron Simpson c...@zip.com.au wrote: | It will work anywhere an expression is allowed, and superficially | doesn't break stuff that exists if as has the lowest precedence. | | Please, no. There is no need for it outside of while expressions, and | anywhere else it's just going to be bad practice. Even if it's | considered an expression, let's only allow it in while expressions. We might just have to differ here. | It would probably mean folding the except/with as uses back into | expressions and out of the control-structural part of the grammar. I can't | see that that would actually break any existing code though - anyone else? | | Yes it would, because the meaning is a bit different in both of those | cases. For except, the result of the expression (an exception class | or tuple of classes) is not stored in the target; the exception | *instance* is. Similarly for with, the result of the expression is | not stored; the result of calling its __enter__ method is, which is | often but not always the same thing. Hmm. Good points. Possibly damning points. except (E1, E2) as c as d: anyone? I should hope not! I may be back to +0 now:-( +0.5 for being able to get at partial expression results somehow, -0.1 for the conflict above. Cheers, -- Cameron Simpson c...@zip.com.au Every \item command in item_list must have an optional argument. - Leslie Lamport, LaTeX -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, 26 Oct 2012 19:12:17 -0400, Devin Jeanpierre wrote: I would like a better iter(), rather than a better while loop. It is irritating to pass in functions that take arguments, and it is impossible to, say, pass in functions that should stop being iterated over when they return _either_ a None or a, say, False. Write a trivial helper function. Not everything has to be a one-liner or a built-in. def iterate_until_none_or_false(func, *args, **kwargs): while True: x = func(*args, **kwargs) # Halt if x is None or False, but not other falsey values. if x is None or x is False: return yield x for x in iterate_until_none_or_false( some_function, 1, 2, c, spam=yummy): process(x) -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 26Oct2012 19:19, Devin Jeanpierre jeanpierr...@gmail.com wrote: | (I've always been partial to :=, personally.) I'm less so. It is hard to type (on my keyboard anyway, that's a shifted keystroke followed by an unshifted one). I mank that up often enough that I would resent it for something as oft used as an assignment. Visually, yes, it's good. I was happy with it in Pascal and its like, though I find the succinctness of plain = very attractive given that it is only available on the left in Python, where it is easy to see and not prone to mixups with == later in an expression. Cheers, -- Cameron Simpson c...@zip.com.au George, discussing a patent and prior art: Look, this publication has a date, the patent has a priority date, can't you just compare them? Paul Sutcliffe: Not unless you're a lawyer. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Fri, Oct 26, 2012 at 8:18 PM, Steven D'Aprano steve+comp.lang.pyt...@pearwood.info wrote: I would like a better iter(), rather than a better while loop. It is irritating to pass in functions that take arguments, and it is impossible to, say, pass in functions that should stop being iterated over when they return _either_ a None or a, say, False. Write a trivial helper function. Not everything has to be a one-liner or a built-in. You are missing the point. I was suggesting that the use case of new syntax might be satisfied instead by new functions, which are clearly preferable to new syntax from the perspective your rebuttal comes from. Indeed, one could write those helper functions, and use them, without any changes to Python being made at all! -- Devin -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Sat, Oct 27, 2012 at 10:19 AM, Devin Jeanpierre jeanpierr...@gmail.com wrote: On Fri, Oct 26, 2012 at 2:23 AM, Chris Angelico ros...@gmail.com wrote: while (client.spop(profile_ids) as profile_id) is not None: print profile_id Why is everyone skirting around C-style assignment expressions as though they're simultaneously anathema and the goal? :) Why should these two statements behave differently? :( with foo() as bar: bar.baz() with (foo() as bar): bar.baz() I don't understand why everyone is so attached to this as syntax. It's confusing because it behaves subtly differently than how it works in with, and it puts the variable on the wrong side of the assignment operator. (I've always been partial to :=, personally.) I'm not attached to as, myself. It puts the variable at the wrong end, and feels backward compared to a convention that exists elsewhere in the language (regular variable assignment). This is a much stronger backwardness issue than the Python ternary operator (which is only backward in comparison to other languages). Personally, I'm quite happy with assignment itself being an expression. But since that's unlikely to be directly accepted in Python, I would be looking for something as general as possible - something that can truly be used _anywhere_ - rather than a specific while-statement enhancement. Capturing partial expression results is an extremely convenient thing to do. ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Steven D'Aprano steve+comp.lang.pyt...@pearwood.info writes: There's no need for it *inside* of while expressions. It doesn't add to the expressiveness of the language, or increase the power of the language, or help people write correct code. It saves one trivial line of code in some, but not all, while loops, at the cost of increasing the complexity of the language and parser. I'm maybe +0.25 on the suggestion but it does save more than one line in the places where it's useful, plus improves clarity. You get to write while (foo() as x) is not None: ... instead of while True: x = foo() if x is not None: break ... which is much uglier. Maybe there are even times when you want while (left() as x) != (right() as y): ... that is even messier when expanded out. There was also the cascaded regexp match example, that happens regularly in real code and that I've hacked various workarounds for, or wished for a Maybe monad. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 01:39 schrieb Ian Kelly: On Wed, Oct 24, 2012 at 5:08 PM, Paul Rubin no.email@nospam.invalid wrote: from itertools import dropwhile j = dropwhile(lambda j: j in selected, iter(lambda: int(random() * n), object())) .next() kind of ugly, makes me wish for a few more itertools primitives, but I think it expresses reasonably directly what you are trying to do. Nice, although a bit opaque. I think I prefer it as a generator expression: j = next(j for j in iter(partial(randrange, n), None) if j not in selected) This generator never ends. If it meets a non-matching value, it just skips it and goes on. The dropwhile expression, however, stops as soon as the value is found. I think # iterate ad inf., because partial never returns None: i1 = iter(partial(randrange, n), None) # take the next value, make it None for breaking: i2 = (j if j in selected else None for j in i1) # and now, break on None: i3 = iter(lambda: next(i2), None) would do the job. Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Paul Rubin no.email@nospam.invalid writes: kind of ugly, makes me wish for a few more itertools primitives JOOI, do you have specific primitives in mind? -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 00:26 schrieb Cameron Simpson: If I could write this as: if re_FUNKYPATTERN.match(test_string) as m: do stuff with the results of the match, using m then some cascading parse decisions would feel a bit cleaner. Where I current have this: m = re_CONSTRUCT1.match(line) if m: ... handle construct 1 ... else: m = re_CONSTRUCT2.match(line) if m: ... handle construct 2 ... else: m = re_CONSTRUCT3.match(line) I could have this: if re_CONSTRUCT1.match(line) as m: ... handle construct 1 ... elif re_CONSTRUCT2.match(line) as m: ... handle construct 2 ... elif re_CONSTRUCT3.match(line) as m: I would do for r in re_CONSTRUCT1, re_CONSTRUCT2, re_CONSTRUCT3: m = r.match(line) if m: handle_construct or maybe actions = {re_CONSTRUCT1: action1, ...} def matching(line, *rr): for r in rr: m = r.match(line) if m: yield r; return for r in matching(line, *actions.keys()): actions[r]() break else: raise NoActionMatched() # or something like that Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 06:50 schrieb Terry Reedy: Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. I would consinder this at least as new substantial than yield_from it as opposed to for i in it: yield i - although I think that was a good idea as well. Although there are quite easy ways to do so, I would appreciate something like the proposed while EXPR as VAR: use VAR if EXPR as VAR: use VAR Of course it is possible to construct a respective workaround such as def maybe_do_that(): if moon == full: with something as val: yield val for val in maybe_do_that(): bla but I would consider this as an abuse of the generator concept. Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 09:21 schrieb Thomas Rachel: I think # iterate ad inf., because partial never returns None: i1 = iter(partial(randrange, n), None) # take the next value, make it None for breaking: i2 = (j if j in selected else None for j in i1) # and now, break on None: i3 = iter(lambda: next(i2), None) would do the job. But, as I read it now again, it might be cleaner to create an own generator function, such as def rand_values(randrange, n, selected): # maybe: selected = set(selected) for the not in while True: val = partial(randrange, n) if val not in selected: break yield val for value in rand_values(...): or, for the general case proposed some posings ago: def while_values(func, *a, **k): while True: val = func(*a, **k): if not val: break yield val Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thu, 25 Oct 2012 11:52:31 +0200, Thomas Rachel wrote: Am 25.10.2012 06:50 schrieb Terry Reedy: Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. I would consinder this at least as new substantial than yield_from it as opposed to for i in it: yield i - although I think that was a good idea as well. Then I think you have misunderstood the purpose of yield from. The fact that you can replace the two lines: for value in another_iterator: yield iterator with a one-liner yield from another_iterator is the least important use- case for yield-from. If that was the only use-case, it probably would not have been allowed, because it adds complication to the language for a trivial gain. The purpose of yield-from is to transfer control to another coroutine, not to save one trivial line of code. [quote] However, if the subgenerator is to interact properly with the caller in the case of calls to send(), throw() and close(), things become considerably more difficult. As will be seen later, the necessary code is very complicated, and it is tricky to handle all the corner cases correctly. A new syntax will be proposed to address this issue. In the simplest use cases, it will be equivalent to the above for-loop, but it will also handle the full range of generator behaviour, and allow generator code to be refactored in a simple and straightforward way. [end quote] http://www.python.org/dev/peps/pep-0380/ yield from is a *huge* win in terms of correctness and power, not just a trivial saving in lines of code. while expr as var is not. -- Steven -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 25-10-12 06:50, Terry Reedy wrote: On 10/24/2012 7:19 PM, Evan Driscoll wrote: On 10/24/2012 05:26 PM, Cameron Simpson wrote: But I'm still -0 on it, because it supplants the glaringly obvious: m = ... assignment with the far less in your face: possibly-long-expr as m and I think it would get quite heavily used, to the detriment of assignment readability in general. At present the nature of most effects is at the left. An assignment is obvious on the left, an if/with/while/etc is visible at the left. In the interest of brainstorming, what about while VAR from EXPR: or something like that? I don't think I like 'from' on a couple counts, but there's probably some word that fits. The op wondered if these proposals have been made before. They have been, and have been rejected. Some of the discussion has been on python-ideas list. But go ahead and brainstorm and discuss. Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. If I recal correctly at one point the following was accepted: do: suite while expr: suite But it was later discarded because of lack of a champion or something like that. -- Antoon Pardon -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 12:50 schrieb Steven D'Aprano: Then I think you have misunderstood the purpose of yield from. Seems so. As I have not yet switched to 3.x, I haven't used it till now. [quote] However, if the subgenerator is to interact properly with the caller in the case of calls to send(), throw() and close(), things become considerably more difficult. As will be seen later, the necessary code is very complicated, and it is tricky to handle all the corner cases correctly. Ok, thanks. Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 2012-10-24, Cameron Simpson c...@zip.com.au wrote: | I must say I really like the parity of Dan's | while EXPR as VAR: | BLOCK | proposal with the with statement. Well, it's nice. But usually EXPR will be a boolean. I guess that depends on what sort of programs you write. In my experience, EXPR is usually a read from a file/socket/pipe that returns '' on EOF. If VAR is not '', then you process, then you process it inside the loop. -- Grant Edwards grant.b.edwardsYow! We're going to a at new disco! gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 2012-10-25, Terry Reedy tjre...@udel.edu wrote: The op wondered if these proposals have been made before. They have been, and have been rejected. Some of the discussion has been on python-ideas list. But go ahead and brainstorm and discuss. Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. I think the new syntax should be introduced in 2.00. There were a number of other big changes between 1.52 and 2.00, so that seems like a good spot to put this change. -- Grant Edwards grant.b.edwardsYow! !! I am having fun!!! at gmail.com -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 16:15 schrieb Grant Edwards: I guess that depends on what sort of programs you write. In my experience, EXPR is usually a read from a file/socket/pipe that returns '' on EOF. If VAR is not '', then you process, then you process it inside the loop. Right. The same as in if regex.search(string) as match: process it But with def if_true(expr): if expr: yield expr you can do for match in if_true(regex.search(string)): process it But the proposed if ... as ...: statment woulkd be more beautiful by far. Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thu, Oct 25, 2012 at 1:21 AM, Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa...@spamschutz.glglgl.de wrote: j = next(j for j in iter(partial(randrange, n), None) if j not in selected) This generator never ends. If it meets a non-matching value, it just skips it and goes on. next() only returns one value. After it is returned, the generator is discarded, whether it has ended or not. If there were no valid values for randrange to select, then it would descend into an infinite loop. But then, so would the dropwhile and the original while loop. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thu, Oct 25, 2012 at 3:52 AM, Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa...@spamschutz.glglgl.de wrote: Am 25.10.2012 06:50 schrieb Terry Reedy: Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. I would consinder this at least as new substantial than yield_from it as opposed to for i in it: yield i - although I think that was a good idea as well. Except that those two are not exactly identical, because yield from also properly delegates sent data and exceptions to the sub-generator. The actual equivalent code for yield from expr(), as given in the PEP, is 39 lines long. This is a substantial feature, not just a little syntactic sugar. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thu, Oct 25, 2012 at 10:36 AM, Ian Kelly ian.g.ke...@gmail.com wrote: On Thu, Oct 25, 2012 at 1:21 AM, Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa...@spamschutz.glglgl.de wrote: j = next(j for j in iter(partial(randrange, n), None) if j not in selected) This generator never ends. If it meets a non-matching value, it just skips it and goes on. next() only returns one value. After it is returned, the generator is discarded, whether it has ended or not. If there were no valid values for randrange to select, then it would descend into an infinite loop. But then, so would the dropwhile and the original while loop. To demonstrate that the code does in fact return: selected = set(range(5)) n = 10 from functools import partial from random import randrange j = next(j for j in iter(partial(randrange, n), None) if j not in selected) j 5 -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 10/25/2012 6:50 AM, Steven D'Aprano wrote: On Thu, 25 Oct 2012 11:52:31 +0200, Thomas Rachel wrote: Am 25.10.2012 06:50 schrieb Terry Reedy: Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. I would consinder this at least as new substantial than yield_from it as opposed to for i in it: yield i - although I think that was a good idea as well. Then I think you have misunderstood the purpose of yield from. The fact that you can replace the two lines: for value in another_iterator: yield iterator with a one-liner yield from another_iterator is the least important use- case for yield-from. If that was the only use-case, it probably would not have been allowed, because it adds complication to the language for a trivial gain. The purpose of yield-from is to transfer control to another coroutine, not to save one trivial line of code. [quote] However, if the subgenerator is to interact properly with the caller in the case of calls to send(), throw() and close(), things become considerably more difficult. As will be seen later, the necessary code is very complicated, and it is tricky to handle all the corner cases correctly. A new syntax will be proposed to address this issue. In the simplest use cases, it will be equivalent to the above for-loop, but it will also handle the full range of generator behaviour, and allow generator code to be refactored in a simple and straightforward way. [end quote] http://www.python.org/dev/peps/pep-0380/ yield from is a *huge* win in terms of correctness and power, not just a trivial saving in lines of code. while expr as var is not. r = yield from g is equivalent to about 40 lines of code as given here http://www.python.org/dev/peps/pep-0380/#formal-semantics It took the developers several tries to first get a version that worked and then to work out the exact details. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Am 25.10.2012 18:36 schrieb Ian Kelly: On Thu, Oct 25, 2012 at 1:21 AM, Thomas Rachel nutznetz-0c1b6768-bfa9-48d5-a470-7603bd3aa...@spamschutz.glglgl.de wrote: j = next(j for j in iter(partial(randrange, n), None) if j not in selected) This generator never ends. If it meets a non-matching value, it just skips it and goes on. next() only returns one value. After it is returned, the generator is discarded, whether it has ended or not. If there were no valid values for randrange to select, then it would descend into an infinite loop. But then, so would the dropwhile and the original while loop. You are completely right. My solution was right as well, but didn't match the problem... Yours does indeed return one random value which is guaranteed not to be in selected. Mine returns random values until the value is not in selected. I just misread the intention behind the while loop... Thomas -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
It seems the topic of this thread has changed drastically from the original message. 1) while EXPR as VAR in no way says that EXPR must be a boolean value. In fact, a use case I've run into commonly in web development is popping from a redis set. E.g. client = StrictRedis() while True: profile_id = client.spop(profile_ids) if not profile_id: break print profile_id In this case, profile_id is None when the loop breaks. It would be much more straightforward (and more Pythonic, IMO), to write: client = StrictRedis() while client.spop(profile_ids) as profile_id: print profile_id 2) Although not originally intended, I kind of like the if statement change proposed later in this thread. It certainly makes sense, since both while and if are conditional statements that are commonly followed by an assignment (or vice versa). 3) I don't think the use case I brought up is solved nicely by wrapping a function / lambda in a generator and using a for loop. E.g. def helper(f): value = f() if value: yield value for profile_id in helper(lambda: client.spop(profile_ids)): print profile_id This works too, I guess def helper(f, *args, **kwargs): value = f(*args, **kwargs) if value: yield value for profile_id in helper(client.spop, profile_ids): print profile_id Either way, it adds too much mental overhead. Every developer on a project has to now insert x lines of code before a for loop or import a helper method from some module, and do this every time this pattern reappears. It's not something I would want to do in one of my projects, since it makes things harder to understand. So all in all, it's a net negative from just doing things the canonical way (with the while / assignment pattern). Dan -- http://mail.python.org/mailman/listinfo/python-list
while expression feature proposal
Hi all, This is my first post to this group--I'm not subscribed, so please CC me in responses. So I'm sure a lot of you have run into the following pattern. I use it all the time and it always has felt a bit awkward due to the duplicate variable assignment. VAR = EXPR while VAR: BLOCK VAR = EXPR I'm curious what the possibility of adding the following to Python as syntactic sugar: while EXPR as VAR: BLOCK Apologies if that has been proposed before. I searched the archives and couldn't find any mention of it. Best, Dan -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Wed, Oct 24, 2012 at 2:40 PM, Dan Loewenherz dloewenh...@gmail.com wrote: So I'm sure a lot of you have run into the following pattern. I use it all the time and it always has felt a bit awkward due to the duplicate variable assignment. VAR = EXPR while VAR: BLOCK VAR = EXPR The idiomatic way to do this is: while True: VAR = EXPR if not VAR: break BLOCK -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 10/24/12 16:34, Ian Kelly wrote: On Wed, Oct 24, 2012 at 2:40 PM, Dan Loewenherz dloewenh...@gmail.com wrote: So I'm sure a lot of you have run into the following pattern. I use it all the time and it always has felt a bit awkward due to the duplicate variable assignment. VAR = EXPR while VAR: BLOCK VAR = EXPR The idiomatic way to do this is: while True: VAR = EXPR if not VAR: break BLOCK It may be idiomatic, but that doesn't stop it from being pretty ugly. I must say I really like the parity of Dan's while EXPR as VAR: BLOCK proposal with the with statement. It also doesn't fall prey to the mistaken-assignment vs. intentional-assignment found in most C-like languages. I could see a pretty reasonable PEP coming from this. -tkc -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Dan Loewenherz dloewenh...@gmail.com writes: VAR = EXPR while VAR: BLOCK VAR = EXPR for VAR in iter(lambda: EXPR, None): BLOCK where the termination sentinel might be False or '' or whatever instead of None. Of course if EXPR is a callable, there's no lambda. while EXPR as VAR: BLOCK This is kind of nice. I wonder if it could generalize with somehow, i.e. use the context manager for EXPR if it has one. Or maybe iter could be generalized so you could pass an arbutrary predicate as termination condition, instead of a single sentinel value. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 24Oct2012 16:54, Tim Chase python.l...@tim.thechases.com wrote: | On 10/24/12 16:34, Ian Kelly wrote: | On Wed, Oct 24, 2012 at 2:40 PM, Dan Loewenherz dloewenh...@gmail.com wrote: | So I'm sure a lot of you have run into the following pattern. I use it | all the time and it always has felt a bit awkward due to the duplicate | variable assignment. | | VAR = EXPR | while VAR: | BLOCK | VAR = EXPR | | The idiomatic way to do this is: | | while True: | VAR = EXPR | if not VAR: | break | BLOCK | | It may be idiomatic, but that doesn't stop it from being pretty | ugly. Yes, but more flexible because it accomodates loops where the natural place for the test is partway through the loop instead of right at the top, which is quite common. | I must say I really like the parity of Dan's | while EXPR as VAR: | BLOCK | proposal with the with statement. Well, it's nice. But usually EXPR will be a boolean. If you're inside the loop you know it's true and don't need VAR. Of course, the glaring counter example is things like regexp tests. I have a heap of code like this: m = re_FUNKYPATTERN.match(test_string) if m: do stuff with the results of the match, using m If I could write this as: if re_FUNKYPATTERN.match(test_string) as m: do stuff with the results of the match, using m then some cascading parse decisions would feel a bit cleaner. Where I current have this: m = re_CONSTRUCT1.match(line) if m: ... handle construct 1 ... else: m = re_CONSTRUCT2.match(line) if m: ... handle construct 2 ... else: m = re_CONSTRUCT3.match(line) I could have this: if re_CONSTRUCT1.match(line) as m: ... handle construct 1 ... elif re_CONSTRUCT2.match(line) as m: ... handle construct 2 ... elif re_CONSTRUCT3.match(line) as m: which is both more concise and also doesn't step inward. But I'm still -0 on it, because it supplants the glaringly obvious: m = ... assignment with the far less in your face: possibly-long-expr as m and I think it would get quite heavily used, to the detriment of assignment readability in general. At present the nature of most effects is at the left. An assignment is obvious on the left, an if/with/while/etc is visible at the left. With statements and except statements have concrete use cases for the as part that aren't doable without it, but the while/if...as form can always be written in the current convention. Cheers, -- Cameron Simpson c...@zip.com.au -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Cameron Simpson c...@zip.com.au writes: if re_FUNKYPATTERN.match(test_string) as m: do stuff with the results of the match, using m class memo: def __call__(f, *args, **kw): self.result = f(*args, **kw) m = memo() if result(re_FUNKYPATTERN.match, test_string): do stuff with the results of the match, using m.result then if re_CONSTRUCT1.match(line) as m: ... handle construct 1 ... elif re_CONSTRUCT2.match(line) as m: ... handle construct 2 ... elif re_CONSTRUCT3.match(line) as m: becomes if m(re_CONSTRUCT1.match, line): .. handle construct 1 ... elif m(re_CONSTRUCT2.match, line): .. handle construct 2 ... -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Thu, Oct 25, 2012 at 9:26 AM, Cameron Simpson c...@zip.com.au wrote: If I could write this as: if re_FUNKYPATTERN.match(test_string) as m: do stuff with the results of the match, using m Then you'd be right there with C-like languages where assignment is an expression :) while (tok = strtok(blah,blah)) ... do something with tok ... ChrisA -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Paul Rubin no.email@nospam.invalid writes: class memo: def __call__(f, *args, **kw): self.result = f(*args, **kw) obviously add return self.result -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 10/24/12 17:26, Cameron Simpson wrote: On 24Oct2012 16:54, Tim Chase python.l...@tim.thechases.com wrote: | On 10/24/12 16:34, Ian Kelly wrote: | The idiomatic way to do this is: | | while True: | VAR = EXPR | if not VAR: | break | BLOCK | | It may be idiomatic, but that doesn't stop it from being pretty | ugly. Yes, but more flexible because it accomodates loops where the natural place for the test is partway through the loop instead of right at the top, which is quite common. Just like the with doesn't stop you from using a try/finally block to do something similar, you can still write mid-loop exits as code currently exists. The proposed syntax just makes coming from other languages easier to translate. | I must say I really like the parity of Dan's | while EXPR as VAR: | BLOCK | proposal with the with statement. Well, it's nice. But usually EXPR will be a boolean. I think the most common use-cases are boolean'ish. The falsehood means stop, but the truthiness value is not merely True. The common use-case I hit is the f = file('foo.bin') while True: data = f.read(CHUNK_SIZE) if not data: break process(data) #not just data=True which tidily becomes while f.read(CHUNK_SIZE) as data: process(data) m = re_FUNKYPATTERN.match(test_string) if m: do stuff with the results of the match, using m If I could write this as: if re_FUNKYPATTERN.match(test_string) as m: do stuff with the results of the match, using m I'm -0 on this. I don't like the pattern, but I'm not sure the if CONDITION as FOO syntax yields nearly the functional readable improvement of while THING as FOO. then some cascading parse decisions would feel a bit cleaner. Where I current have this: m = re_CONSTRUCT1.match(line) if m: ... handle construct 1 ... else: m = re_CONSTRUCT2.match(line) if m: ... handle construct 2 ... else: m = re_CONSTRUCT3.match(line) For those, I often end up putting the regexps in a list and iterating accordingly (which I have done multiple times): regexes = [ re_one, re_two, re_three, ] for regex in regexes: m = regex.match(line) if m: handle(m) break else: doh() Granted, it does expect that you want to handle the results uniformly, but this could (usually) be mitigated with a dispatch function as well regex_dispatches = [ (re_one, handle1), (re_two, handle2), (re_three, handle3), ] for regex, fn in regex_dispatches: m = regex.match(line): if m: fn(m, extra_context) break else: doh() But I'm still -0 on it, because it supplants the glaringly obvious: m = ... assignment with the far less in your face: possibly-long-expr as m If it were replacing standard assignment, I'd be as off-the-charts -1 as possible. Yech. But when cued by the while and indentation, it's not quite so bad. It still feels yuckyâ„¢ in an if, but I find the improvement in the while is certainly worthwhile. With statements and except statements have concrete use cases for the as part that aren't doable without it, but the while/if...as form can always be written in the current convention. The syntax for the with *could* have been something like with foo = file(foo.txt): for line in foo: pass but the as was chosen and I think it makes sense in the context. -tkc (To me, the if CONDITION as VAR feels much like the ternary evaluation: x = foo if bar else baz which made it into official syntax; I find the while CONDITION as VAR much more readable/valuable in light of both) -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Wed, Oct 24, 2012 at 3:54 PM, Tim Chase python.l...@tim.thechases.com wrote: It may be idiomatic, but that doesn't stop it from being pretty ugly. I must say I really like the parity of Dan's while EXPR as VAR: BLOCK proposal with the with statement. It also doesn't fall prey to the mistaken-assignment vs. intentional-assignment found in most C-like languages. I could see a pretty reasonable PEP coming from this. Often though the while test is not a simple boolean test of VAR. For example: j = int(random() * n) while j in selected: j = int(random() * n) It also doesn't flow quite as naturally. with x as y is grammatically correct English. while x as y is not, and I wonder how easily it might be confused for while x is y, which is valid Python and means something completely different. -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 25Oct2012 09:40, Chris Angelico ros...@gmail.com wrote: | On Thu, Oct 25, 2012 at 9:26 AM, Cameron Simpson c...@zip.com.au wrote: | If I could write this as: | |if re_FUNKYPATTERN.match(test_string) as m: | do stuff with the results of the match, using m | | Then you'd be right there with C-like languages where assignment is an | expression :) | | while (tok = strtok(blah,blah)) ... do something with tok ... Well, yes, that's the core convenience of the suggested syntax. But without the =/== accident opportunity. But with another assignment that doesn't look like an asisgnment syntax. Like I said, I'm -0. -- Cameron Simpson c...@zip.com.au Be smart, be safe, be paranoid. - Ryan Cousineau, cour...@compdyn.com DoD#863, KotRB, KotKWaWCRH -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 24Oct2012 15:37, Paul Rubin no.email@nospam.invalid wrote: | Cameron Simpson c...@zip.com.au writes: |if re_FUNKYPATTERN.match(test_string) as m: | do stuff with the results of the match, using m | | class memo: | def __call__(f, *args, **kw): | self.result = f(*args, **kw) | | m = memo() | if result(re_FUNKYPATTERN.match, test_string): |do stuff with the results of the match, |using m.result | | then | | if re_CONSTRUCT1.match(line) as m: | ... handle construct 1 ... | elif re_CONSTRUCT2.match(line) as m: | ... handle construct 2 ... | elif re_CONSTRUCT3.match(line) as m: | | becomes | |if m(re_CONSTRUCT1.match, line): | .. handle construct 1 ... |elif m(re_CONSTRUCT2.match, line): | .. handle construct 2 ... Cute. Not sure I like it, but cute:-) -- Cameron Simpson c...@zip.com.au If you do not read the paper, you are uninformed. If you do read the paper, you are misinformed. - Mark Twain -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
Ian Kelly ian.g.ke...@gmail.com writes: j = int(random() * n) while j in selected: j = int(random() * n) from itertools import dropwhile j = dropwhile(lambda j: j in selected, iter(lambda: int(random() * n), object())) .next() kind of ugly, makes me wish for a few more itertools primitives, but I think it expresses reasonably directly what you are trying to do. -- http://mail.python.org/mailman/listinfo/python-list
Re: Re: while expression feature proposal
On 10/24/2012 05:26 PM, Cameron Simpson wrote: But I'm still -0 on it, because it supplants the glaringly obvious: m = ... assignment with the far less in your face: possibly-long-expr as m and I think it would get quite heavily used, to the detriment of assignment readability in general. At present the nature of most effects is at the left. An assignment is obvious on the left, an if/with/while/etc is visible at the left. In the interest of brainstorming, what about while VAR from EXPR: or something like that? I don't think I like 'from' on a couple counts, but there's probably some word that fits. Evan signature.asc Description: OpenPGP digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On Wed, Oct 24, 2012 at 5:08 PM, Paul Rubin no.email@nospam.invalid wrote: from itertools import dropwhile j = dropwhile(lambda j: j in selected, iter(lambda: int(random() * n), object())) .next() kind of ugly, makes me wish for a few more itertools primitives, but I think it expresses reasonably directly what you are trying to do. Nice, although a bit opaque. I think I prefer it as a generator expression: j = next(j for j in iter(partial(randrange, n), None) if j not in selected) -- http://mail.python.org/mailman/listinfo/python-list
Re: while expression feature proposal
On 10/24/2012 7:19 PM, Evan Driscoll wrote: On 10/24/2012 05:26 PM, Cameron Simpson wrote: But I'm still -0 on it, because it supplants the glaringly obvious: m = ... assignment with the far less in your face: possibly-long-expr as m and I think it would get quite heavily used, to the detriment of assignment readability in general. At present the nature of most effects is at the left. An assignment is obvious on the left, an if/with/while/etc is visible at the left. In the interest of brainstorming, what about while VAR from EXPR: or something like that? I don't think I like 'from' on a couple counts, but there's probably some word that fits. The op wondered if these proposals have been made before. They have been, and have been rejected. Some of the discussion has been on python-ideas list. But go ahead and brainstorm and discuss. Keep in mind that any new syntax has to be a substantial improvement in some sense or make something new possible. There was no new syntax in 3.2 and very little in 3.3. -- Terry Jan Reedy -- http://mail.python.org/mailman/listinfo/python-list