There are other none-aware operator candidates worth discussing:
- None-conditional function invocation:
fn?() - None-aware await:
await? - None-conditional assignment:
a?.b = c - Non-none-coalesing operator
I’m particularly interested in a ‘non-none-coalescing’ operator.
None-conditional function invocation – fn?()
This is mentioned as a rejected idea in @cdce8p’s PEP. I agree that ?( is sufficiently different in nature from ?. and ?[, but I guess most users would expect its presence among them.
I actually didn’t know for a long time you could do fn?.() in Javascript/Typescript. I don’t recall ever encountering it. I wonder why did they decided to make it ?.( and not ?( for brevity. Either way, its use is likely too rare to be worth it, but I also don’t see much other reason against it, since, to me, it’s pretty clear what the meaning is.
Also, it would be a bit of a shame to see a.foo?.__call__(arguments) become idiomatic rather than a.foo?(arguments).
None-aware await – await?
If await is given an expression involving ?. then a TypeError is bound to occur. The ‘none-aware await’ operator await? helps by returning None instead of raising TypeError when given None.
I saw that there was some awkwardness surrounding the use of ?. in an await expression in C#. The ‘null-conditional await’ operator is currently being proposed for that language. A SO answer suggests the following workaround:
await (this.MyObject?.MyMethod() ?? Task.CompletedTask)
The problem is dodged in Typescript since any value is awaitable in that language. Although you could write something similar to ?? Task.CompletedTask by ?? Promise.resolve(null).
The issue we have for Python is that we don’t have a succinct way to write a resolved Future. Without await?, if ?. were added to the language we’d end up with a lot of this stuff in async code:
v = obj?.method()
if v: await v
Or
completed_future = Future()
completed_future.set_result(None)
...
await obj?.method() ?? completed_future
Null-conditional assignment – a?.b = c
This was added very recently to C# (v14). This feature lets you use ?. on the LHS of an assignment. The C#-ers seem to like it because apparently the following code pattern is very common:
if foo is not None:
foo.bar = baz
Useful?
Non-none coalescing operator – &?
If ?? is like or, what is the analog to and? It would be the ‘non-none-coalescing’ operator which can be thought of as the inverse of the none-coalescing operator. It says: “if the left operand is none, keep the none, otherwise take the right-hand operand”.
The obvious symbol candidate for a ‘non-none-coalescing’ operator that comes to mind is ‘!?’. I’m going to elect ‘&?’ though since it parallels with and better without suggesting any… unnecessary inverse-ness.
This operator doesn’t currently exist in any language, but I think it has a lot of use potential and the pattern occurs a lot in my code. The operator is essentially used to replace the ternary: None if foo is None else bar(foo) → foo &? bar(foo).
My issue with the ternary is that many prefer the is not version in order to put the juicier part at the front of the expression, while others like to deal with the null first. My own preference seems to depend on the weather, and having to make the decision every time slows me down. If we had a non-none-coalescing operator there would be one obvious way to write this pattern.
