On Tue, Jun 23, 2020 at 3:06 PM Emily Bowman <silverback...@gmail.com> wrote:
> Can you have case (x,x): ? I haven't tried the implementation, but it's > not addressed in the PEP that I see, and if that's legal, then _ is > effectively just a style choice, rather than a functional one, and there's > no reason it shouldn't also be a named match. > Good question. It's explicitly forbidden by the PEP, in the "Name pattern" section: While matching against each case clause, a name may be bound at most once, having two name patterns with coinciding names is an error. An exception is made for the special single underscore (``_``) name; in patterns, it's a wildcard that *never* binds:: match data: case [x, x]: # Error! ... case [_, _]: print("Some pair") print(_) # Error! Note: one can still match on a collection with equal items using `guards`_. Also, ``[x, y] | Point(x, y)`` is a legal pattern because the two alternatives are never matched at the same time. I should add that if you want to check for two values in different positions being equal, you need to use a guard: match data: case [x, y] if x == y: print("Two equal values") On Tue, Jun 23, 2020 at 12:11 PM Brett Cannon <br...@python.org> wrote: > I will say that trying to follow > https://github.com/python/peps/blob/master/pep-0622.rst#runtime-specification > was really hard. Any chance of getting some pseudo-code that shows how a > match is performed? Otherwise all of that wording tries so hard to be a > spec that I found it hard to follow in my head in how things function. > Sorry about that. This section was subject to heavy editing recently and lost clarity. I will try to make it better! Writing it as pseudo code will take a little time, but I will give it a try. > For instance, "When __match_args__ is missing (as is the default) or None, > a single positional sub-pattern is allowed to be passed to the call" is > really misleading as it seems that a "sub-pattern" in this case is just > going to be a constant like `[1, 2, 3]`. Otherwise how does `["<"|">"]` or > `[1, 2, *_]` get represented as a "single positional sub-pattern" (if > either of those examples is possible)? The use of the term "sub-pattern" > feels misleading because while you may consider even constant patterns a > "pattern", going that generic feels like any pattern should fit in that > definition when in fact it seems to only be an object where a direct > equality check is done. > > It seems the way things work is basically: > > 1. `__match__(obj)` returns a proxy object to have Python match against; > it is passed in the thing that `match` is running against, returning `None` > if it know there's no chance a match will work > 2. If `__match_args__` is present, then it is used to map positional > arguments in the pattern to attributes on the proxy object > 3. From there the `match` functionality does a bunch of comparisons > against attributes on the proxy object to see if the match works > > Is that right? That suggests all the work in implementing this for objects > is coming up with a way to serialize an object to a proxy that makes > pattern matching possible. > Yes, that's right, and the protocol was defined carefully so that the author of __match__ doesn't have to do any pattern matching -- all they have to do is produce an object that has the right attributes, and the interpreter does the rest. Note that it is __match__'s responsibility to check isinstance()! This is because __match__ may not want to use isinstance() but instead check for the presence of certain attributes -- IOW, the class pattern supports duck typing! (This was a little easter egg. :-) > One thing I see mentioned in examples but not in the `__match__` > definitions is how mappings work. Are you using `__match_args__` to map > keys to attributes? Or are you using `__getitem__` and that just isn't > directly mentioned? Otherwise the section on how `__match__` is used only > mentioned attributes and never talks about keys. > Oh, __match__ is *only* used for class patterns. Mapping patterns are done differently. They don't use __getitem__ exactly -- the PEP says Matched key-value pairs must already be present in the mapping, and not created on-the-fly by ``__missing__`` or ``__getitem__``. For example, ``collections.defaultdict`` instances will only match patterns with keys that were already present when the ``match`` block was entered. You shouldn't try to depend on exactly what methods will be called -- you should just faithfully implement the Mapping protocol. -- --Guido van Rossum (python.org/~guido) *Pronouns: he/him **(why is my pronoun here?)* <http://feministing.com/2015/02/03/how-using-they-as-a-singular-pronoun-can-change-the-world/>
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/N7USX5OB2NEPO25JLTMTI4SUQ2CB7WLY/ Code of Conduct: http://python.org/psf/codeofconduct/