While this post is a fun exploration, I think __subclasshook__ isn’t as bad as presented. isinstance(cls, collections.abc.Mapping) is great. We get structural typing using the same semantics as nominal typing.
When pattern matching dropped I was surprised at how limited it was trying to be, so I did something similar to get it to do regexp matching/capturing. Pro tip: attribute access also has side effects :)
In general I have mixed feelings about this feature. Some languages just don’t have customizable destructuring at all, and that seems entirely respectable. But Python clearly isn’t trying to be one of them, and yet this feature is still weirdly limited. It feels like the language designers are determined to impose some random opinions on every new thing they add.
I appreciate where you’re coming from and shared your mixed feelings for a long time.
However now I feel like the easy answer is - don’t do stunt coding with your pattern matching, keep it simple and readable, and we all get a nice alternative to the endless waves if if/else/ :)
Yeah, reading the PEP felt discouraging for this reason. But overall, Python is about having one flavor of crazy punch. Unlike Ruby, where literally anything going on could be a flavor of crazy punch.
ruby can have a class match objects in a case statement without having to overload the subclassing mechanism - case b; when a calls a === b under the hood, and you can define an === operator for your class or whatever.
You can match objects in Python too, without abusing ABCs. But abusing ABCs is how you get the wild stuff like effectful matching and non-monotonic types.
The following is the logical flow for matching a class pattern against a subject value:
If name_or_attr is not an instance of the builtin type , raise TypeError.
If the subject value is not an instance of name_or_attr (tested via isinstance()), the class pattern fails.
you don’t need an ABC, but you do need to override the isinstance check, whereas ruby separates out the notion of isinstance and case matching so that you can override the latter without changing the former. on the other hand, i think ruby only lets you override isinstance checks on the object and not the class (i.e. you can have an object foo say it is an instance of anything, but not a class Bar say anything is an instance of it) so python definitely has more potential for weirdness there :)
I think AppleScript is a better candidate for this comparison than Perl? Perl is infamous for being write-only rather than read-only. AppleScript is infamous for being fairly easy to read but almost impossible to edit.
I very much disagree, and also like I say above, I think language comparisons like this add very little value and serve mostly as incendiaries.
Most uses of Python’s new pattern matching feature are very readable to practically anyone. You’re looking at a trained practitioner contorting their code into a knot - stunt coding because they CAN and because doing so helps those of us who study the language understand it more deeply.
You’re looking at a trained practitioner contorting their code into a knot - stunt coding because they CAN and because doing so helps those of us who study the language understand it more deeply.
Yeah the motivation is less “look how dumb pattern matching is!” (it’s not dumb at all) and more “look how much fun you can have with a programming language without writing an actual program, just doing weird things”
Python is Python and Perl is Perl. They’re both great languages which have more or less readable features, and all of this - what’s readable and what’s not, is so incredibly dependent on the fuzzy aesthetic preferences the human doing the reading.
While this post is a fun exploration, I think
__subclasshook__
isn’t as bad as presented.isinstance(cls, collections.abc.Mapping)
is great. We get structural typing using the same semantics as nominal typing.That’s a reasonable use of subclasshook! This post is all about unreasonable uses
This is a very exciting idea that I’m going to need to think about later. I love a good hack.
Makes me wonder why
case Not(DistanceMetric)():
is invalid syntax. Logically, this should compose.I wonder if mixing brackets (
Not[DistanceMetric]()
) would workIn Python? Unlikely - square brackets are reserved for arrays AFAIK
You can use
__getitem__
/__setitem__
to overload them.in normal expressions yes, but pattern matching is a totally different syntax and AST.
When pattern matching dropped I was surprised at how limited it was trying to be, so I did something similar to get it to do regexp matching/capturing. Pro tip: attribute access also has side effects :)
In general I have mixed feelings about this feature. Some languages just don’t have customizable destructuring at all, and that seems entirely respectable. But Python clearly isn’t trying to be one of them, and yet this feature is still weirdly limited. It feels like the language designers are determined to impose some random opinions on every new thing they add.
I appreciate where you’re coming from and shared your mixed feelings for a long time.
However now I feel like the easy answer is - don’t do stunt coding with your pattern matching, keep it simple and readable, and we all get a nice alternative to the endless waves if if/else/ :)
Yeah, reading the PEP felt discouraging for this reason. But overall, Python is about having one flavor of crazy punch. Unlike Ruby, where literally anything going on could be a flavor of crazy punch.
I think you can do everything here in Scala with extractor objects.
ruby can have a class match objects in a
case
statement without having to overload the subclassing mechanism -case b; when a
callsa === b
under the hood, and you can define an===
operator for your class or whatever.You can match objects in Python too, without abusing ABCs. But abusing ABCs is how you get the wild stuff like effectful matching and non-monotonic types.
i was referring to this bit in the docs:
you don’t need an ABC, but you do need to override the
isinstance
check, whereas ruby separates out the notion of isinstance and case matching so that you can override the latter without changing the former. on the other hand, i think ruby only lets you override isinstance checks on the object and not the class (i.e. you can have an objectfoo
say it is an instance of anything, but not a classBar
say anything is an instance of it) so python definitely has more potential for weirdness there :)Off topic, but I’m getting a 404 when I try to save this link… wonder if that’s affecting anyone else?
It’s all very readable, even considering it’s entirely uneditable. Does python make a better Perl? Write once, then read only forever?
I think AppleScript is a better candidate for this comparison than Perl? Perl is infamous for being write-only rather than read-only. AppleScript is infamous for being fairly easy to read but almost impossible to edit.
This particular feature of python makes python compete head to head.
I very much disagree, and also like I say above, I think language comparisons like this add very little value and serve mostly as incendiaries.
Most uses of Python’s new pattern matching feature are very readable to practically anyone. You’re looking at a trained practitioner contorting their code into a knot - stunt coding because they CAN and because doing so helps those of us who study the language understand it more deeply.
Yeah the motivation is less “look how dumb pattern matching is!” (it’s not dumb at all) and more “look how much fun you can have with a programming language without writing an actual program, just doing weird things”
Python is Python and Perl is Perl. They’re both great languages which have more or less readable features, and all of this - what’s readable and what’s not, is so incredibly dependent on the fuzzy aesthetic preferences the human doing the reading.