Hi David and Steve,

There is hardly anything that needs to be added to your comments, of course.  However, I consider these explicitly named attributes in the class pattern to be one of the most difficult aspects of our pattern matching proposal, which is something I just want to briefly acknowledge.  Although there are good reasons for using the syntax as proposed, understanding that ``Spam(a=x)`` assigns the attribute ``a`` to the variable ``x`` is not quite as intuitive and straight forward.

Using the curly braces for that purpose might help in that we instantly think differently and more in line with dictionaries. This small clue could potentially have quite an impact on readability.  This idea has thus a huge advantage over the square brackets not because of PEP 637, but because it might change the way we look at the code at hand.

The reason why I would not favour this specific syntax is because we expect that the predominant case would be to just write ``Spam(1, 2)`` without the attribute names.  It is even possible to mix and match the two, which would then lead to something like ``Spam{1, b=2}``.  In that case, the advantage of the dictionary-like notation might just evaporate I assume, leaving behind a notation that turns out to be unusual and somewhat annoying in the overwhelming majority of cases.

There are a few other concepts and ideas behind it all, which I do not want to go into unless there is demand for it, but part of it is the idea that we want to be as much as possible in line with the syntax already used in iterable unpacking, say.

Kind regards,
Tobias



Quoting David Mertz <mertz@gnosis.cx>:

On Sat, Nov 21, 2020 at 12:23 PM Steven D'Aprano <steve@pearwood.info> wrote:

Clearly Spam(a=1, b=2) does not necessarily result in an instance with
attributes a and b. But the pattern `Spam(a=1, b=2)` is intended to be
equivalent to (roughly):

    if (instance(obj, Spam)
        and getattr(obj, a) == 1
        and getattr(obj, b) == 2)

it doesn't imply that obj was *literally* created by a call to
the constructor `Spam(a=1, b=2)`, or even that this call would be
possible.

 
I think this explanation makes me not worry about the fact that `Spam(a=1, b=2)` in a pattern looks a lot like a constructor.  Like some other commenters, I was vaguely bothered that the identical spelling might have these different meanings in different contexts.  But I think a match case just clearly enough IS a different context that using slightly different intuitions is no real conceptual stretch for remembering or teaching it.
 
As a strawman, we could use different syntax for "match the thing of class Spam that has attributes with these values:
 
match eggs:
    case Spam[a=1, b=2]: ...
 
Or:
 
match eggs:
    case Spam{a=1, b=2}: ...
 
Well, the square brackets COULD mean something different if PEP 637 is adopted.  But even supposing the curly braces could be fit into the grammar.  Yes, it sort of suggests the connection between dictionaries and Spam.__dict__.  But it still reads as "this is something special that I have to think about a little differently."
 
Even where there are capture variables, I think I'd be completely comfortable thinking about the different context for:
 
match eggs:
    case Spam(a=x, b=2): ...
 
--
The dead increasingly dominate and strangle both the living and the
not-yet born.  Vampiric capital and undead corporate persons abuse
the lives and control the thoughts of homo faber. Ideas, once born,
become abortifacients against new conceptions.