
On Thu, May 21, 2020 at 02:50:00PM +0200, Alex Hall wrote:
On Thu, May 21, 2020 at 12:27 AM James Lu <jamtlu@gmail.com> wrote:
This is already valid in 3.8, so we should forget about overloading := with a second meaning.
def func(x=(a:=expression), y=a+1): def func(x:=options):
These two syntaxes do not conflict with each other.
Technically no, but there is potential to confuse beginners.
Forget beginners, I know that will confuse me! Technically, *yes*, they do conflict. Ask yourself what the walrus operator `:=` means in Python 3.8, and you have a single answer: - "it's like `=` only it works as an operator". Now ask yourself what the walrus operator means if James' proposal is accepted. The answer becomes: - "well, that depends on where you see it..." or: - "in this context, it's like `=` only it works as an operator" - "but in this context, it changes the meaning of assignment completely to something very different to how the `=` works everywhere else" That's certainly a conflict. This isn't necessarily a deadly objection. For example, the `@` symbol in decorator syntax and the `@` symbol in expressions likewise conflicts: @decorate(spam @ eggs) def aardvark(): ... but both uses of the `@` symbol well and truly proved their usefulness. Whereas in this case: - the walrus operator is still new and controversial; - James' proposed `:=` in signatures hasn't proven it's usefulness.
What about:
def func(x=:options):
As a beginner, it took me months to remember to use colons in dict displays instead of equals signs, and they are two extremely common operations that beginners learn from practically Day 1. Even now, 20 years later, I still occasionally make that error. (Especially if I'm coding late at night.) You're proposing to take one uncommon operator, `:=`, and flip the order of the symbols to `=:`, as a beginner-friendly way to avoid confusion. As if people don't get confused enough by similar looking and sounding things that differ only in slight order. To steal shamelessly from the stand-up comedian Brian Regan: I before E except after C, or when sounding like A like in NEIGHBOUR and WEIGH, on weekends and holidays, and all throughout May, you'll be wrong no matter what you say.
or a more realistic example:
def func(options=:{}):
Add annotations and walrus operator: def flummox(options:dict=:(a:={x: None})): and we now have *five* distinct meanings for a colon in one line.
Personally I think the best way forward on this would be to accept PEP 505.
For the benefit of those reading this who haven't memorised all multiple-hundreds of PEPs by ID, that's the proposal to add None-aware operators to the language so we can change code like: if arg is None: arg = expression into arg ??= expression In this thread, there has been hardly any mention of the times where None is a legitimate value for the argument, and so the sentinal needs to be something else. I have written this many times: _MISSING = object() def func(arg=_MISSING): if arg is _MISSING: arg = expression Null-coalescing operators will help in only a subset of cases where we want late-binding of default arguments. -- Steven