Thanks! Bit of discussion below about precedence, but thanks for spotting the typos.

On 18Jul2018 1318, MRAB wrote:
On 2018-07-18 18:43, Steve Dower wrote:
Grammar changes
---------------

The following rules of the Python grammar are updated to read::

      augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' |
'^=' |
                  '<<=' | '>>=' | '**=' | '//=' | '??=')

      power: coalesce ['**' factor]
      coalesce: atom_expr ['??' factor]
      atom_expr: ['await'] atom trailer*
      trailer: ('(' [arglist] ')' |
                '[' subscriptlist ']' |
                '?[' subscriptlist ']' |
                '.' NAME |
                '?.' NAME)

The precedence is higher than I expected. I think of it more like 'or'. What is its precedence in the other languages?

Yes, I expected this to be the contentious part. I may have to add a bit of discussion.

Mostly, I applied intuition rather than copying other languages on precedence (and if you could go through my non-git history, you'd see I tried four other places ;) ). The most "obvious" cases were these::

    a ?? 1 + b()

    b ** a() ?? 2

In the first case, both "(a ?? 1) + b()" and "a ?? (1 + b())" make sense, so it's really just my own personal preference that I think it looks like the first. If you flip the operands to get "b() + a ?? 1" then you end up with either "b() + (a ?? 1)" or "(b() + a) ?? 1", then it's more obvious that the latter doesn't make any sense (why would __add__ return None?), and so binding more tightly than "+" helps write sensible expressions with fewer parentheses.

Similarly, I feel like "b ** (a() ?? 2)" makes more sense than "(b ** a()) ?? 2", where for the latter we would have to assume a __pow__ implementation that returns None, or one that handles being passed None without raising a TypeError.

Contrasting this with "or", it is totally legitimate for arithmetic operators to return falsey values.

As I open the text file to correct the typos, I see this is what I tried to capture with:

Inserting the ``coalesce`` rule in this location ensures that expressions
resulting in ``None`` are naturally coalesced before they are used in
operations that would typically raise ``TypeError``.

Take (2 ** a.b) ?? 0. The result of __pow__ is rarely going to be None, unless we train all the builtin types to do so (which, incidentally, I am not proposing and have no intention of proposing), whereas something like "2 ** coord?.exponent" attempting to call "2.__pow__(None)" seems comparatively likely. (Unfortunately, nobody writes code like this yet :) So there aren't any real-life examples. Originally I didn't include "??" in the proposal, but it became obvious in the examples that the presence of None-propagating operators ?. and ?[] just cause more pain without having the None-terminating operator ?? as well.)

Inserting the ``coalesce`` rule in this location ensures that expressions
resulting in ``None`` are natuarlly coalesced before they are used in

Typo "natuarlly".

Thanks.

      assert a == 'value'
      assert b == ''
      assert c == '0' and any(os.scandir('/'))

Wouldn't the last assertion fail, because c == 0?

Correct, another typo.

Cheers,
Steve
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to