PEP 622: Re-wrote deferred ideas section (#1483)

The section that explains the decision to defer an extended
custom matching protocol has been transformed into a section
that defers custom matching altogether.
This commit is contained in:
Talin 2020-07-01 07:57:00 -07:00 committed by GitHub
parent 2e8df86101
commit 31d5ffe9ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 54 additions and 34 deletions

View File

@ -1568,41 +1568,35 @@ Note that you **can** use the same name more than once in alternate choices::
.. _extended matching:
Extended matching protocol
--------------------------
Custom matching protocol
------------------------
During the initial design discussions for this PEP, there were a lot of ideas
thrown around about exotic custom matchers: ``IsInstance()``, ``InRange()``,
``RegexMatchingGroup()`` and so on. In fact, part of the proposal included
a new Python standard library module containing a menagerie of such diverse
matchers.
thrown around about custom matchers. There were a couple of motivations for
this:
However, these matchers require a much more flexible and expensive custom
matching protocol. In particular, it meant that the ``__match__`` method
would need to have an additional "match signature" argument which would
let it know exactly what values the pattern was seeking.
* Some classes might want to expose a different set of "matchable" names
than the actual class properties.
* Some classes might have properties that are expensive to calculate, and
therefore shouldn't be evaluated unless the match pattern actually needed
access to them.
* There were ideas for exotic matchers such as ``IsInstance()``,
``InRange()``, ``RegexMatchingGroup()`` and so on.
* In order for built-in types and standard library classes to be able
to support matching in a reasonable and intuitive way, it was believed
that these types would need to implement special matching logic.
Part of the argument against this more flexible protocol was that this
match signature argument would be expensive to construct. Due to the dynamic
nature of Python name binding, it could not be a constant, but would have
to be created anew each time; and there is no guarantee that the ``__match__``
function would even use this argument in its internal logic.
These customized match behaviors would be controlled by a special
``__match__`` method on the class name. There were two competing variants:
The decision to postpone this feature came with a realization that this is
not a one-way door; that an extended matching protocol could be added later,
using a variety of techniques (such as defining a new custom match magic
method with a different name) to signal that a class wished to opt-in
in the extended protocol and that the VM should compute the extended signature
object.
* A 'full-featured' match protocol which would pass in not only
the target object to be matched, but detailed information about
which attributes the specified pattern was interested in.
* A simplified match protocol, which only passed in the target object,
and which returned a "proxy object" (which in most cases could be
just the target) containing the matchable attributes.
The authors of this PEP expect that the ``match`` statement will evolve
over time as usage patterns and idioms evolve, in a way similar to what
other "multi-stage" PEPs have done in the past. When this happens, the
extended matching issue can be revisited.
There was an idea to send partial context like literals only, or
custom pattern objects that will provide the full context. For example
the below match would generate the following call::
Here's an example of one version of the more complex protocol proposed::
match expr:
case BinaryOp(left=Number(value=x), op=op, right=Number(value=y)):
@ -1620,11 +1614,37 @@ the below match would generate the following call::
False,
)
This would allow faster ``__match__()`` implementations and give better
support for customization in user-defined classes. There is however a big
downside to this: it would make the basic implementation of this method quite
complicated. Also, there would be a performance penalty if the user did not
treat the pattern object properly.
One drawback of this protocol is that the arguments to ``__match__``
would be expensive to construct, and could not be pre-computed due to
the fact that, because of the way names are bound, there are no real
constants in Python. It also meant that the ``__match__`` method would
have to re-implement much of the logic of matching which would otherwise
be implemented in C code in the Python VM. As a result, this option would
perform poorly compared to an equilvalent ``if``-statement.
The simpler protocol suffered from the fact that although it was more
performant, it was much less flexible, and did not allow for many of
the creative custom matchers that people were dreaming up.
Late in the design process, however, it was realized that the need for
a custom matching protocol was much less than anticipated. Virtually
all the realistic (as opposed to fanciful) uses cases brought up could
be handled by the built-in matching behavior, although in a few cases
an extra guard condition was required to get the desired effect.
Moreover, it turned out that none of the standard library classes really
needed any special matching support other than an appropriate
``__match_args__`` property.
The decision to postpone this feature came with a realization that this is
not a one-way door; that a more flexible and customizable matching protocol
can be added later, especially as we gain more experience with real-world
use cases and actual user needs.
The authors of this PEP expect that the ``match`` statement will evolve
over time as usage patterns and idioms evolve, in a way similar to what
other "multi-stage" PEPs have done in the past. When this happens, the
extended matching issue can be revisited.
Parameterized Matching Syntax