←back to thread

317 points est | 1 comments | | HN request time: 0.236s | source
Show context
sametmax ◴[] No.17448716[source]
I will be happy to be able to do:

    while (bytes := io.get(x)): 
and:

    [bar(x) for z in stuff if (x := foo(z))] 
Every time Python adds an expression counterpart to an existing statement (lambdas, intensions, ternary...) there is a (legit) fear it will be abused.

But experience tells that the slow and gradual pace of the language evolution combined with the readability culture of the community don't lead that way.

While we will see code review breaking materials in the wild, I believe that the syntax will mostly be used sparingly, as other features, when the specific needs arise for it.

After all, it's been, as usual, designed with this in mind: "=" and ":=" are mutually exclusive. You don't use them in the same context.

The grammar makes sure of it most of the time, and for the rare ambiguities like:

    a = b
vs

    (a := b)
The parenthesis will discourage pointless usage.

My bet is that we will see essentially rare but useful and expressive use cases in productions, which is exactly the goal.

Given the month of debates around this, I think it's a fine compromise.

Like many, I would have preferred the use of the "as" keyword instead of a new operator, since it's already used to bind things to names in imports, context managers and try/except.

However, the new syntax has 2 advantages: it reads the same way than the original operator, and it supports type hints out of the box.

replies(6): >>17449142 #>>17449634 #>>17453453 #>>17453473 #>>17454371 #>>17456196 #
gshulegaard ◴[] No.17453473[source]
I agree that I would have preferred "as"...but that said I am struggling to think of a reason this is needed.

    while (bytes := io.get(x)):
Would currently be written:

    bytes = io.get(x)
    while bytes:
And likewise:

    [bar(x) for z in stuff if (x := foo(z))]
is equivalently:

    [bar(foo(z)) for z in stuff if foo(z)]
Perhaps this is just my personal opinion but I don't really think the ":=" (or "as" for that matter) adds much in the way of clarity or functionality. I guess at the end of the day I am neutral about this addition...but if there isn't a clear upside I usually think it's better to have less rather than add more.
replies(4): >>17453490 #>>17453580 #>>17454284 #>>17516119 #
wizpig64 ◴[] No.17454284[source]
This second example:

    [bar(x) for z in stuff if (x := foo(z))]
is not equivalent to:

    [bar(foo(z)) for z in stuff if foo(z)]
because here, foo(z) will be called twice. If foo is an expensive operation or performs some other magic in the background that you don't want to call a second time, := lets you express this behavior without having to break your expression out into a huge for-if-append code block:

    output = []
    for z in stuff:
        x = foo(z)
        if x:
            output.append(bar(x))
Of course, the above verbose language might end up being a better code in the end, because mashing together a bunch of terse code is often not very readable. But in real life, transforming a comprehension into a loop is just a bunch of work that gets in the way of me trying to complete a task.

When I'm developing out an idea and just want to see if the code works and passes my tests, I would rather have the option to insert behavior swiftly without having to reformat an entire block of code. Then when reviewing my code or deciding whether to make it reusable for something else, I can go back and clean things up.

replies(3): >>17454426 #>>17454756 #>>17456065 #
1. gshulegaard ◴[] No.17454756[source]
I'm aware `foo(z)` gets called twice, but I wouldn't choose to break it into the `for` loop you mention:

    [bar(x) for x in map(foo, stuff) if x]
I was just trying to be as close to the original as possible.

I do find it odd you call out the calling of `foo` twice as a performance drain but then use the chief example of:

> When I'm developing out an idea and just want to see if the code works and passes my tests, I would rather have the option to insert behavior swiftly without having to reformat an entire block of code.

Tests are not something I (personally) consider to be performance sensitive. But like I said I am sort of neutral on this change. I don't really see a massive benefit to it, so I would personally air on the side of "don't add" but I'm not mad it's being added. It's a "meh" for me.