Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 103 additions & 15 deletions pep-0622.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1517,27 +1517,17 @@ ambiguous with capture patterns. Five other alternatives were considered:
disambiguate grouping in patterns, e.g. in ``Point(x, y=(y :=
complex()))``.

* Introduce a special symbol, for example ``.``, ``$``, or ``^`` to
indicate that a given name is a constant to be matched against, not
* Introduce a special symbol, for example ``?``, ``.``, ``$``, or ``^`` to
indicate that a given name is a value to be matched against, not
to be assigned to. An earlier version of this proposal used a
leading-dot rule::

match entree[-1]:
case .spam: ... # Compares entree[-1] == spam.
case side: ... # Assigns side = entree[-1].

While potentially useful, it introduces strange-looking new syntax
without making the pattern syntax any more expressive. Indeed,
named constants can be made to work with the existing rules by
converting them to ``Enum`` types, or enclosing them in their own
namespace (considered by the authors to be one honking great idea)::

match entree[-1]:
case Sides.SPAM: ... # Compares entree[-1] == Sides.SPAM.
case side: ... # Assigns side = entree[-1].

If needed, the leading-dot rule (or a similar variant) could be
added back later with no backward-compatibility issues.
See `stronger assignment target consistency`_ for
further discussion of this rejected proposal.

* There was also on idea to make lookup semantics the default, and require
``$`` or ``?`` to be used in capture patterns::
Expand All @@ -1556,6 +1546,10 @@ ambiguous with capture patterns. Five other alternatives were considered:

* None of the proposed syntaxes have any precedent in Python.

* All other name binding operations in Python (assignment statements,
assignment expressions, for loops, class definitions, function definitions,
import statements, comprehensions) use bare names for targets

* It would break the syntactic parallels of the current grammar::

match coords:
Expand Down Expand Up @@ -1752,7 +1746,8 @@ the other uses of ``...`` in Python, but that water is already under
the bridge.)

Another proposal was to use ``?``. This could be acceptable, although
it would require modifying the tokenizer.
it would require modifying the tokenizer. For further discussion of this
possibility, refer to `stronger assignment target consistency`_.

Also, ``_`` is already used
as a throwaway target in other contexts, and this use is pretty
Expand All @@ -1775,6 +1770,99 @@ conflicts with the use of ``_`` as a marker for translatable strings
and an alias for ``gettext.gettext``, as recommended by the
``gettext`` module documentation.

.. _stronger assignment target consistency:

Pursuing stronger semantic consistency with assignment targets
--------------------------------------------------------------

Two aspects of the match pattern proposal in this PEP are deliberately similar
to syntax used in assignment targets: simple name binding and sequence matching.

The simple name binding alignment means that the following two code snippets
have the same effect at runtime (binding `x` to the same target as `y`)::

match y:
case x:
pass

# has the same effect as
x = y

Similarly, the alignment of the sequence matching syntax with iterable unpacking
means that the following two code snippets have the same effect at runtime for
sequences that fit the desired pattern (although the match example will not
consume iterators, and allows the handling of the case where the given
value does NOT match the expected pattern to be more easily customised)::

match z:
case x, y:
pass

# has the same effect as the following for 2-item sequences
x, y = z

This alignment with assignment target syntax does NOT extend to constant value
expressions or wildcard matches.

Where `x.y = z` sets the attribute `x.y` to the same target as `z`, the
following doesn't perform a binding operation at all::

match z:
case x.y:
print("This only runs if 'x.y == z', it doesn't set x.y")

This distinction could be made explicit at a syntactic level by requiring a
marker prefix (such as `?`) on value lookups in match patterns, with attempts to
use ordinary attribute lookup syntax being a syntax error. Using a marker symbol
could also be used to allow the match value lookup to be an arbitrary
subexpression, rather than being limited to attribute lookups::

match z:
case ?x.y:
print("This runs if 'x.y == z'")
case ?x:
print("This runs if 'x == z'")
case ?f():
print("This runs if 'f() == z'")
case ?match_value[i]:
print("This runs if 'match_value[i] == z'")

Optionally, the marker prefix could even be required when match values are
literals or keywords, but actually doing that would be a separate design
decision unrelated to the question of semantic consistency with assignment
target syntax (using a literal or keyword as an assignment target is a
syntax error so, unlike attribute lookups, there's no semantic conflict even if
match expressions allow them without any further syntactic marker).

For wildcard matches, while `_` is often used as a throwaway variable by
convention, it otherwise operates as a normal identifier in Python. If a marker
prefix for match value expressions were introduced, then it would be possible
for this PEP to use `_` the same way in match patterns as it is used in
assignment targets (i.e. like any other identifier), and instead allow the
bare value lookup prefix as a wildcard that matches any value without binding
it::

match x:
case _:
# This would bind the same way '_ = x' does
assert _ is x

match x:
case ?:
print("This would match without binding")

In addition to potentially making the match pattern syntax easier to learn, the
other benefit offered by pursuing stronger semantic consistency with assignment
targets is that it would leave open the possibility of a future PEP that
proposed allowing the use of more match pattern syntax in assignment targets,
where failure to match the target pattern automatically raised ``ValueError``.

However, the PEP authors believe that requiring an explicit marker prefix for
value lookup match patterns would not provide sufficent benefits to make it
worthwhile to pursue stronger semantic consistency with assignment target
syntax.


Use some other syntax instead of ``|`` for OR patterns
------------------------------------------------------

Expand Down