Interesting PEP. Actually it reminds me Crystal language ‘case’. But I have some comments

 

> An excerpt from PEP622 [1]:

 

> Let us start from some anecdotal evidence: isinstance() is one of the

> most called functions in large scale Python code-bases (by static

> call count). In particular, when analyzing some multi-million line

> production code base, it was discovered that isinstance() is the

> second most called builtin function (after len()). Even taking into

> account builtin classes, it is still in the top ten. Most of such

> calls are followed by specific attribute access.

>

> There are two possible conclusions that can be drawn from this

> information:

>

> *    Handling of heterogeneous data (i.e. situations where a variable

> can take values of multiple types) is common in real world code.

 

It can be handled with modern Python’ types.

 

> *    Python doesn't have expressive ways of destructuring object data

> (i.e. separating the content of an object into multiple variables).

>

 

Actually the second reason when isinstance() is used (related to “destructuring”) is the case with inheritance. So the isinstance() switches cases between different successors of some base class. And there would be such a kind of “destructuring”:

 

if isinstance(something, Window): return something.handle

elif isinstance(something, Button): return something.wnd_hnd

else: raise SomeError(“blah-blah”)

 

which is anti-pattern sure: in the case of inheritance, the getters must be delegated to concrete implementations.

 

> I just want to say a big thank you to the Haskell creators for giving

> us a tool to efficiently write real world code (as it is called above).

 

The reason why ML family languages have pattern-matching is:

 

           data X = X1 Int Int | X2 String

 

Python and similar languages don’t support algebraic data types directly (and usually you simulate it with inheritance), so you don’t need pattern-matching and such a way of “destructuring” at all. What is

 

           case x of X1 n m -> …

 

? It’s a leak of abstraction. A leak of knowledge about INTERNAL structure, internal representation of the object, which is bad. So, if you think that pattern-matching is very good (aka “real world”) , IMHO you are not right here. So C# designers added EXPLICIT support of deconstruct:

 

private static (string, int, double) QueryCityData(string name) {…}

 

so you don’t leak information about internal representation of your data and use just common external general representation like tuples, for example. The second helper in C# is a new `switch` syntax, which is very close to pattern-matching, but again: it’s limited with public fields, so only a developer decides which part of his class will be available for matching, and no any leak again. This idea was crystallized in Perl: you don’t know what is the object but do know that it can be used in scalar context/list context/hash context and so on. In OOP, for example, you don’t know what is the object but you know that you can use it as a container of items, which can be enumerable/modifiable-in-place/whatever… This is a right solution from a language designer point of view, but not a ML-style pattern matching.

 

And this understanding is often used in Haskell too – some types are “hidden” for the user: you have only smart constructors/getters but not knowledge about inner structure of the object. IMHO ML-style pattern matching is outdated feature, more typical for 70-80s languages.

 

---

Best regards, Paul