Skip to content

Commit cb55229

Browse files
committed
Add new sections to rejected ideas + common objections
1 parent 092e36f commit cb55229

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

peps/pep-0999.rst

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,46 @@ Furthermore, defining the short-circuiting behavior that way would have
984984
been a deviation from the already established behavior in
985985
languages like JS [#js_short_circuiting]_ and C# [#csharp]_.
986986

987+
Change ``primary`` rule to be right-recursive
988+
---------------------------------------------
989+
990+
The ``primary`` grammar rule as it is defined [#py_grammar]_ is
991+
left-recursive. This can make it difficult to reason about especially
992+
with regards to the `Short-circuiting`_ and `Grouping`_ behavior.
993+
994+
It was therefore proposed to make the ``None``-aware access operators
995+
part of the ``primary`` rule right-recursive instead. The expression
996+
``a.b?.c[0].func()`` would then roughly be parsed as:
997+
998+
.. code-block:: python
999+
1000+
NoneAwareAttribute(
1001+
base=Attribute(
1002+
expr=Name(identifier="a"),
1003+
identifier="b"
1004+
)
1005+
tail=[
1006+
AttributeTail(identifier="c"),
1007+
SubscriptTail(slice=Constant(value=0)),
1008+
AttributeTail(identifier="func")
1009+
CallTail(args=[], keyword=[])
1010+
]
1011+
)
1012+
1013+
While this approach would clearly define which parts of an expression
1014+
would be short-circuited, it has several drawbacks. To implement it at
1015+
least three additional AST nodes have to be added ``AttributeTail``,
1016+
``SubscriptTail`` and ``CallTail``. As these are right-recursive now,
1017+
reusing code from the ``Attribute``, ``Subscript`` and ``Call`` nodes
1018+
might prove difficult. Not to mention that the ``NoneAware*`` nodes
1019+
would contain parts that are both left- and right-recursive which
1020+
would be confusing.
1021+
1022+
In comparison the proposed `Grammar changes`_ are intentional kept to
1023+
a minimum. The ``None``-aware access operators should behave more or
1024+
less like a drop-in replacement for ``.`` and ``[ ]``, only with the
1025+
behavior outline in this PEP.
1026+
9871027

9881028
Common objections
9891029
=================
@@ -1069,6 +1109,38 @@ a match statement or data traversal libraries from PyPI.
10691109
See the `Exception-aware operators`_ section for more details why
10701110
this was rejected.
10711111

1112+
Short circuiting is difficult to understand
1113+
-------------------------------------------
1114+
1115+
Some have pointed the `Short-circuiting`_ behavior might be difficult
1116+
to understand and suggested to remove it in favor of a simplified
1117+
proposal.
1118+
1119+
It is true that using short-circuiting that way is new to Python and
1120+
as such unknown. That closest analogs would be boolean expressions like
1121+
``a or b``, ``a and b`` which do also short-circuit the expression if
1122+
the first value is truthy or falsy respectively. However, while
1123+
the details are complex, the behavior itself is rather intuitive.
1124+
To understand it, it is often enough to know that once a subexpression
1125+
for an ``optional`` value evaluates to ``None``, the result will be
1126+
``None`` as well. Any subsequent attribute access, subscript or call
1127+
will be skipped. In the example below, if ``a.b`` is ``None``, so will
1128+
be ``a.b?.c``:
1129+
1130+
::
1131+
1132+
a.b?.c
1133+
^^^
1134+
1135+
On a technical level, removing short-circuiting would make it difficult
1136+
to detect if ``not-optional`` attributes suddenly started to return
1137+
``None`` as well. See `Remove short-circuiting`_ in the rejected ideas
1138+
section for more details on that.
1139+
1140+
Lastly, the short-circuiting behavior as proposed is identical to that
1141+
of other languages like TS [#ts]_, JS [#js_short_circuiting]_ and
1142+
C# [#csharp]_.
1143+
10721144
Just use ...
10731145
------------
10741146

@@ -1233,6 +1305,8 @@ Footnotes
12331305
(https://pypi.org/project/nonesafe/)
12341306
.. [#pymaybe] PyPI: pymaybe
12351307
(https://pypi.org/project/pymaybe/)
1308+
.. [#py_grammar] Python documentation: Full Grammar specification
1309+
(https://docs.python.org/3/reference/grammar.html)
12361310
12371311
12381312
Copyright

0 commit comments

Comments
 (0)