PEP 635: Various updates

- Added sections on Backwards Compatibility, Security Implications and Reference Implementation
- Resolve remaining TODOs
This commit is contained in:
Guido van Rossum 2020-10-21 16:49:48 -07:00
parent d3f060d0ca
commit 3a59572771
1 changed files with 60 additions and 17 deletions

View File

@ -18,17 +18,11 @@ Resolution:
Abstract
========
**NOTE:** This draft is incomplete and not intended for review yet.
We're checking it into the peps repo for the convenience of the authors.
This PEP provides the motivation and rationale for PEP 634
("Structural Pattern Matching: Specification"). First-time readers
are encouraged to start with PEP 636, which provides a gentler
introduction to the concepts, syntax and semantics of patterns.
TODO: Go over the feedback from the SC and make sure everything's
somehow addressed.
Motivation
==========
@ -80,13 +74,11 @@ Several other common Python idioms are also relevant:
case BinOp("+", a, BinOp("*", b, c)):
# Handle a + b*c
- TODO: Other compelling examples?
We believe that adding pattern matching to Python will enable Python
users to write cleaner, more readable code for examples like those
above, and many others.
For a more academic approach to this proposal, see [1]_.
For a more academic discussion to this proposal, see [1]_.
Pattern Matching and OO
@ -130,8 +122,6 @@ binary methods). Pattern matching is structurally better suited to handle
such situations of multi-dispatch, where the action to be taken depends on
the types of several objects to equal parts.
TODO: Could we say more here?
Patterns and Functional Style
-----------------------------
@ -144,9 +134,15 @@ mixed with classes or data classes.
Pattern matching is particularly suitable for picking apart such data
structures. As an extreme example, it's easy to write code that picks
a JSON data structure using ``match``.
a JSON data structure using ``match``::
TODO: Example code.
match json_pet:
case {"type": "cat", "name": name, "pattern": pattern}:
return Cat(name, pattern)
case {"type": "dog", "name": name, "breed": breed):
return Dog(name, breed)
case _:
raise ValueError("Not an suitable pet")
Functional programming generally prefers a declarative style with a focus
on relationships in data. Side effects are avoided whenever possible.
@ -161,14 +157,10 @@ This section provides the rationale for individual design decisions.
It takes the place of "Rejected ideas" in the standard PEP format.
It is organized in sections corresponding to the specification (PEP 634).
TODO: Cross-check against PEP 622 as well as (private) SC feedback.
Overview and Terminology
------------------------
TODO: What to put here?
Much of the power of pattern matching comes from the nesting of subpatterns.
That the success of a pattern match depends directly on the success of
subpattern is thus a cornerstone of the design. However, although a
@ -994,6 +986,12 @@ understanding of the mapping pattern's semantics.
To avoid overly expensive matching algorithms, keys must be literals or
value patterns.
There is a subtle reason for using ``get(key, default)`` instead of
``__getitem__(key)`` followed by a check for ``AttributeError``: if
the subject happens to be a ``defaultdict``, calling ``__getitem__``
for a non-existent key would add the key. Using ``get()`` avoids this
unexpected side effect.
**Example** using the Mapping pattern::
def change_red_to_blue(json_obj):
@ -1075,6 +1073,9 @@ an object lacks an attribute specified by the pattern, the match fails.
declaration of formal parameters, which allows calling functions with
positional arguments rather than naming all the parameters.
This is a class attribute, because it needs to be looked up on the class
named in the class pattern, not on the subject instance.
The syntax of class patterns is based on the idea that de-construction
mirrors the syntax of construction. This is already the case in virtually
@ -1099,6 +1100,14 @@ thinking about data, its flow and manipulation. This equally extends to
the explicit construction of instances, where class patterns ``C(p, q)``
deliberately mirror the syntax of creating instances.
The special case for the built-in classes ``bool``, ``bytearray``
etc. (where e.g. ``str(x)`` captures the subject value in ``x``) can
be emulated by a user-defined class as follows::
class MyClass:
__match_args__ = ["__myself__"]
__myself__ = property(lambda self: self)
**Type annotations for pattern variables.**
The proposal was to combine patterns with type annotations::
@ -1218,6 +1227,34 @@ Or you would combine these ideas to write ``Node(right=y)`` so as to require
an instance of ``Node`` but only extract the value of the `right` attribute.
Backwards Compatibility
=======================
Through its use of "soft keywords" and the new PEG parser (PEP 617),
the proposal remains fully backwards compatible. However, 3rd party
tooling that uses a LL(1) parser to parse Python source code may be
forced to switch parser technology to be able to support those same
features.
Security Implications
=====================
We do not expect any security implications from this language feature.
Reference Implementation
========================
A `feature-complete CPython implementation
<https://github.com/brandtbucher/cpython/tree/patma>`_ is available on
GitHub.
An `interactive playground
<https://mybinder.org/v2/gh/gvanrossum/patma/master?urlpath=lab/tree/playground-622.ipynb>`_
based on the above implementation was created using Binder [2]_ and Jupyter [3]_.
References
==========
@ -1226,6 +1263,12 @@ References
(Accepted by DLS 2020. The link will go live after Nov. 17;
a preview PDF can be obtained from the first author.)
.. [2] Binder
https://mybinder.org
.. [3] Jupyter
https://jupyter.org
Copyright
=========