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:
parent
2e8df86101
commit
31d5ffe9ca
88
pep-0622.rst
88
pep-0622.rst
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue