←back to thread

317 points est | 10 comments | | HN request time: 1.91s | source | bottom
Show context
gbfowler ◴[] No.17448582[source]
It is not syntactic sugar, "x := 10" is an assignment expression in contrast with "x = 10", which is a statement.

Hence the former can be used in contexts like "if x := 10: pass", which is the whole point of the PEP.

replies(2): >>17448624 #>>17448651 #
Aardwolf ◴[] No.17448624[source]
Why is it not syntactic sugar? It looks like convenience. You could argue everything above machine language is syntactic sugar.
replies(5): >>17448721 #>>17448736 #>>17448847 #>>17448880 #>>17448984 #
cup-of-tea ◴[] No.17448880[source]
Synactic sugar means the same thing can be achieved without the sugar. How could you achieve this without the new expression?
replies(1): >>17448901 #
1. est ◴[] No.17448901[source]
by writing extra lines?

I'd prefer more lines for readability reasons.

replies(2): >>17448929 #>>17449056 #
2. cup-of-tea ◴[] No.17448929[source]
How would you do this?

    if (match := re.match(r1, s)):
        o = match.group(1)
    elif (match := re.match(r2, s)):
        o = match.group(1)
replies(2): >>17449096 #>>17449827 #
3. chriswarbo ◴[] No.17449056[source]
> by writing extra lines?

That doesn't seem possible (see my sibling comments). You might be able to write a different program, which might be similar (e.g. same return value, most of the time), but I don't think there's anything that's equivalent.

This is an important distinction! For example, let's say you're given a program that uses a lot of `x := y` expressions. You're asked to back-port this to an older Python version, which doesn't have `x := y`. What do you do? If there's an equivalent expression, you can just swap them out; you could even automate it with a keyboard macro, since there's no need to think about it.

If, on the other hand, you only know how to write similar code, you can't be as confident. Some examples of where "similar" programs can end up behaving differently are:

- The application makes heavy use of threading

- There are lots of magic methods defined, like `__getattribute__`, which can alter the meaning of common Python expressions (e.g. `foo.bar`)

- Those magic methods cause global side effects which the program relies on, so that they have to get triggered in the correct order

- The program manipulates implementation features, like `locals()`, `func_globals`, `__class__`, etc.

- The software is a library, which must accept arbitrary values/objects given by users

- It makes use of hashes, e.g. to check for data in an existing database, and those hashes may depend on things like the order of insertion into internal properties

Whilst it's perfectly reasonable to curse whoever wrote such monstrous code, that doesn't help us backport it. We would have to tread very carefully, and write lots of tests.

> I'd prefer more lines for readability reasons

Verbosity and readability are not the same thing. Overly verbose code might have easier to understand parts, whilst obscuring the big picture of what it's actually doing. A classic example is assembly: each instruction is pretty easy, e.g. "add the value of register A to register B", "jump to the location stored in register C if register B is non-positive", etc. Yet we can pluck a page of disassembled machine code from, say, the middle of LibreOffice and have no idea what problem it's meant to be solving. (I posted a rant about this at https://news.ycombinator.com/item?id=16223583 ).

4. PurpleRamen ◴[] No.17449096[source]

    match = re.match(r1, s)
    if match:
        o = match.group(1)
    else:
        match = re.match(r2, s)
        if match:
            o = match.group(1)
or a bit shorter:

    match = re.match(r1, s)
    if not match:
        match = re.match(r2, s)
    if match:
        o = match.group(1)
You could also just loop:

    for pattern in (r1, r2, ...):
        match = re.match(pattern, s)
        if match:
            o = match.group(1)
            break
    else:
        do_failure_handling()
But this goes a bit beyond the original question.
replies(1): >>17449950 #
5. est ◴[] No.17449827[source]
well, that looks easy.

    m = re.match(r1, s) or re.match(r2, s)
    o = m.group(1) if m else None
replies(1): >>17449896 #
6. cup-of-tea ◴[] No.17449896{3}[source]
I made a mistake in my question. The arguments to group shouldn't have been the same. What I want to get at is when the two branches are completely different code.
replies(1): >>17454693 #
7. cup-of-tea ◴[] No.17449950{3}[source]
I made a mistake in the question, it should have been:

    if (match := re.match(r1, s)):
        o = match.group(1)
        # plus some code here
    elif (match := re.match(r2, s)):
        o = match.group(2)
        # plus some other code here
In this case only your first solution works, I think. Leaving aside that having those deeply nested ifs is incredibly ugly, I find it hard to accept that something which completely changes the possible structure of the code is just "syntactic sugar".
replies(2): >>17450207 #>>17455182 #
8. PurpleRamen ◴[] No.17450207{4}[source]
It's the syntactic sugars job to beautify the ugly. And your example is also a bit unfair, because you also use another syntactic sugar, the elif, to make it more beautyful. It only falls back to the ugly solution because I can't sweeten sugar for a similar dish.

But the overall question is: when is the sugar just syntactical, and at what point does it become a complete new taste?

9. est ◴[] No.17454693{4}[source]
I think it's a case where PEP 572 tries to fix bad library design.

re.match shouldn't return None at all. I often write helper functions like:

    matcher = lambda r, s: getattr(re.match(r, s), 'group', lambda i: '')
    o = matcher(r1, s)(1) or matcher(r2, s)(3)
here matcher have a fixed, static return type, string.
10. Demiurge ◴[] No.17455182{4}[source]
Why is it incredibly ugly when it actually conveys the explicit logic of that which is happening? Can the logic be simplified? Are there any unnecessary characters? I don't see that. This is why I like Python, it's easy to read, and it is easy to refactor and see how you can improve the logic.