5 ms·
It's going to look quite alien at first, but this is a great demonstration of how this will actually help the language. The regexp examples are a common one alw
by cnorthwood 8y ago
It's going to look quite alien at first, but this is a great demonstration of how this will actually help the language. The regexp examples are a common one always felt overly verbose when I do that. The risk is that it makes it very easy to write overly terse code, I don't think I'm the only dev who's ever written a "clever" list comprehension only to come back to it later and struggle to get my head round it.
- nerdponx 8y agoSeeing this in action, I think I kind of hate it. One of the basic aspects of idiomatic Python that I like the most is the fact that doing multiple things at once is discouraged. Multiple assignment (x,y = a,b) is possible but not typically done except where it conveys special intent. This seems to be replacing foo = check_foo() if foo: do_foo() with if (foo := check_foo()): do_foo() which goes against that idea.
- misnome 8y agoThis can replace that, sure, but I think it's more meant to be replacing things like: foo = check_foo() while foo: do_foo() foo = check_foo() With while foo := check_foo(): do_foo() which is a case that hasn't had an elegant solution in the past. Another, if example, where you want to call a function based on the result of a check, but don't want to make that check more than once: foo = check_foo() if foo: do_foo(foo) else: other_foo = check_other_foo() if other_foo: do_other_foo(other_foo) else: # Continue with if foo := check_foo(): do_foo(foo) elif other_foo := check_other_foo() do_other_foo(other_foo) elif .....: Yes, all of this has been possible and there are other ways to do it, but this expresses the problem very concisely and has less nesting at the cost of a slightly more complicated syntax. I find these rewritten examples easier to parse than the originals. Pulling things out of comprehensions is pretty neat too. Other than a few cases (e.g. these) I don't see this suited or intended for extremely wide usage, but no worse than any other complex idiom that people can overuse.
- mehrdadn 8y agoI agree the check_foo() duplication was bad, but was this workaround really so bad? while 1: foo = check_foo() if not foo: break do_foo(foo) Its only downside was taking 2 extra lines, not actual understandability.
- int_19h 8y agoIt makes the intent of the loop less clear, since now the condition is tucked away somewhere in the middle of the body, even though it's really a precondition.
- mehrdadn 8y agoI'm torn on this, because although it's easy to say that for a toy example like this, when these "preconditions" evolve over time, you get things like: while 1: now = time() if now > prev_time + UPDATE_TIME: report_progress() foo = check_foo() if not foo: break if foo < 0: print_error(); break do_foo(foo) prev_time = now Now, was it really dictating a precondition? Or was it actually dictating a postcondition? Or both or neither? Would you really want these responses to dictate the locations of the condition in the syntax? Because it seems to me that forcing yourself to put these conditions in the loop condition just makes the code extremely ugly and difficult to evolve (requiring you to duplicate code or have very convoluted expressions with assignments).
- int_19h 8y agoThe biggest thing this gives, IMO, is the ability to filter on a computed value in a comprehension, and then use that computed value as the result. It's something that's needed quite often if you use comprehensions heavily, and there's no good workaround for it currently (you can use a nested "for" over a 1-element tuple to create a named binding, but it's much uglier, has more overhead, and readability is basically non-existent).
- misnome 8y ago
- kristoff_it 8y agobut at the same time, having foo exist only inside the block that actually makes use of it seems a good idea
- wodenokoto 8y agofoo = check_foo() if foo: do_foo() Why would you ever write that? Just if check_foo(): do_foo()
- cyphar 8y agoWhat if you need to use the value of 'foo' more than once?
- wodenokoto 8y agoThen I would make that clear from the example foo = check_foo() if foo: do_foo(foo)
- cyphar 8y agoPEP-572 has a very good section that talks about how people love to bike-shed about examples. Examples that are too simple are ridiculed with "I wouldn't do it that way", and examples that are too complicated are ridiculed with "that's far too convoluted to be a common use-case". I think this comment falls along this type of bike-shedding.
- wodenokoto 8y agoObviously we disagree on where the example lands. My original post was in good faith. "Why would you need a new construct for something that is already solved?" To me, adding the variable assigned before the if-statement, inside, or after the if-statement would have made it clear why one might write the original code that way, and why a new type of assignment could be helpful. Looking at the downvotes, that is apparently not a common confusion.
- raverbashing 8y ago> which goes against that idea. Then remove 'for' as it iterates and checks for a condition at the same time Remove list comprehensions, as they do multiple things in one single statement Remove map/filter/zip as they iterate and apply a function Remove the '+=' operator (though x = x + 1 still do more than one thing at the same time)
- est 8y agoI think it's the re package's fault. It's badly designed. re.match should return a match object no matter what, and .group() should return strings, empty string if non were matched. We don't even need anything remotely :=
- yorwba 8y agoWhat about regular expressions that match the empty string? There might be ways the regular expression library could be designed better, but making re.match return a match when there's no match is not an improvement.
- PurpleRamen 8y agoNo match is also a match. The problem here is that it's bad design design if a function returns multiple different types of result. Generally there should only be one type of result to make handling reliable. It if's neccessary, you can still test for an empty result, making it the optional case that it is.
- est 8y agoand what's the use case for that? The main problem here is that you can't chain re.match().group() because None has no .group() Why do you want to match empty string with a group?
- yorwba 8y agoThe use case for a regular expression that matches the empty string is detecting whether something starts with an optional pattern. E.g. '(foo)?' to match the optional prefix 'foo'. FWIW if you really want re.match().group() to always return a string, you can just wrap all your regular expressions with '(...)?'. The reason why someone might want to be able to distinguish between "no match" and "the match is empty" is writing code that takes any arbitrary regular expression and uses it as a filter. Then someone else could pass in an expression that matches empty and everything works together nicely.
- sirk390 8y ago