From 3a5957277131f9e3a2431ca99523535d387a28d0 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Wed, 21 Oct 2020 16:49:48 -0700 Subject: [PATCH] PEP 635: Various updates - Added sections on Backwards Compatibility, Security Implications and Reference Implementation - Resolve remaining TODOs --- pep-0635.rst | 77 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 17 deletions(-) diff --git a/pep-0635.rst b/pep-0635.rst index 5b16ebd34..edeec98bc 100644 --- a/pep-0635.rst +++ b/pep-0635.rst @@ -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 +`_ is available on +GitHub. + +An `interactive playground +`_ +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 =========