On 18/07/18 19:43, Steve Dower wrote: > When a ``None``-aware operator is present, the left-to-right evaluation > may be > short-circuited. For example, ``await a?.b(c).d?[e]`` is evaluated:: > > _v = a > if _v is not None: > _v = _v.b > _v = _v(c) > _v = _v.d > if _v is not None: > _v = _v[e] > await _v
## NB I only skimmed most of this thread after reading the PEP, so I ## ## apologize if this has been discussed before and I missed it. ## I quite like the general idea, but I'm nervous about a rather fundamental aspect: This adds a special case in which you can't add parentheses to an expression involving a chain of operators to make precedence and evaluation order clear. To use your example, a ?? 2 ** b ?? 3 === (a ?? 2) ** (b ?? 3) # fine In the present day, a or 2 + 3 * c() === a or (2 + (3 * (c()))) a.b(c).d[e] === (((a.b)(c)).d)[e] # silly, but true. Short-circuiting doesn't break this. With and and or, the expression that's short-circuited away is a self-contained expression in imagined (or actual) parentheses. With this ?. operator, the chain a?.b(c).d?[e] can no longer be broken into sub-expressions, but becomes one single, long, atomic expression, just like a comparison chain. If I try: (a?.b)(c).d?[e] # TypeError: 'NoneType' object is not callable a?.(b(c).d?[e]) # SyntaxError, and illogical Also, where does this end? if a is None, is (a?.b,c()) equal to None or (None, c())? Presumably the latter because of operator precedence, but still. Is introducing the idea of an "attribute reference, call and subscription" chain worth it? This could be fixed by adding a maybe-call ?( operator, which would allow a?.b?(C())?.d?[E()] === ((((a?.b) ?( C() )) ?.d) ?[ E() ]) _v = a _v = _v.b if _v is not None else None _v = _v(C()) if _v is not None else None _v = _v.d if _v is not None else None _v = _v[E()] if _v is not None else None with None falling all the way through, and the calls to C() and E() being short-circuited out. Of course you need either attribute-call-subscription chains or ‘?()’ maybe-calls for ‘?.’ to be worthwhile at all, since otherwise you can't write None-aware method calls. Aside: other languages cited From a quick look at the C# docs linked in the PEP [1], I'm guessing that C# allows A?.B?.C?.Do(E), but does not allow A?.B?.C.Do(E). Does anybody know? Obviously method calls work differently in C# than in Python. Dart? I dunno. The docs aren't as thorough. Am I missing something? Cheers Thomas [1] https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/