Smartmatch in 5.27.7

What happened?

In the latest development release of perl, smartmatch changed quite a bit.

Almost everything you believed about smartmatching is now wrong

No really, everything. All previous rules are gone except a single one: you can smartmatch against any object that overloads smartmatching (the only "objects" that overload them out of the box are qr// regexps).

Matching against a scalar value? Gone. Matching against a list of values? Also gone.

when is no more.

The when keyword is gone, split into two keywords: whereis and whereso; one smartmatches the value against the current subject and the other does a simple boolean check much like if. I'll let you guess which is which. This split is for good reasons (when sometimes does one and sometimes the other, sometimes depending on things like optimizations), but that doesn't make this any more intuitive.

use 5.010/use 5.028 won't guard you from this.

It would have been possible to support both behaviors, because the old behavior is already using feature.pm. In fact one could even enable old and new style when at the same time in a scope without problems. None of this was done though.

My suggestions

new smartmatch should be more useful.

Right now one can't do anything with it without a helper library (like my Smart::Match). That's just silly.

The insanity of old style matching was that the overloads depended on both operands, this gave rise to hard to predict behavior, but that doesn't mean one can't define useful behavior that only depends on the right side that follows the most common use-cases. In particular matching scalars stringwise, and making $foo ~~ ["bar", "baz" ] mean $foo in [ "bar", "baz" ].

This should be opt-in

Despite retroactively adding warnings the feature is experimental, it has become a widely used feature. This change is breaking a (yet unknown but significant) number of CPAN modules, and likely much more code in darkpan. Breaking this unless strictly necessary is dumb.

And it isn't necessary. We can easily only enable the new behavior when asked for. That way we can improve smartmatching without breaking a decade worth of smartmatching code.

We need better words

whereso and whereis are way too confusing. I'm not sure what that would look like but this just doesn't cut it.

Above all, we need a better process

Somehow, p5p made a fundamental breaking change to the language without even trying to involve the wider community. This blogpost shouldn't have been the first time the wider community hears about it. And we need that wider community IMHO because no one on p5p (myself included) has the kind of language design talent that's required to do the sort of thing we did here. I don't know what the solution would look like exactly, but I like this process even less than I like the outcome so far. I must admit I'm somewhat jealous of Python's PEP process, though I'm not sure that would work without a language designer to guide it.

15 Comments

The new keywords are whereis and whereso. I can see "whereis", but at the moment "whereso" conveys nothing to me. Maybe documenting some rationale for at least "whereso" would help -- sort of like the mnemonics in perlvar.

My experience with the new keywords and my extremely eclectic list of installed modules is:

  • B::Keywords - Does not use given/whatever, but needs to return the correct list. Currently the tests fail under 5.27.7 because it tests against keywords.h. Presumably this problem has a solution, though, because of the addition of say() in 5.10.
  • ODF::lpOD - Makes extensive use of given/when. Of course, this is pretty far downstream, and I am not sure it is maintained these days.
  • PPI - Installs and runs. Of course, it has no PPI::Statement classes specific to the new keywords, but (based on a very small sample) the parse appears sane.
  • Try::Tiny - Does not use given/whatever, but tests to be sure it works inside a given/when. The test fails to compile under 5.27.7.
  • Type::Tiny - Does not use given/whatever, but tests to be sure it works inside a given/when. The test fails to compile under 5.27.7.

Unfortunately when/whereis/whereso are not among the keywords exposed as functions in CORE::, so it is hard for me to see how to write code that works across the divide other than (yukk!) stringy eval or (double yukk!) source filters. In order to keep things going for myself I may have to take a whack at writing CPAN prefs files that are applied or not based on the Perl version.

Kudos to Karen Etheridge, who already has a version of Try-Tiny that installs under 5.27.7. The fix was to skip_all() in a BEGIN block if $] does not pass muster.

That should be OK for Type-Tiny as well.

Here here. I've stated this many times before. It's always fallen on deaf ears.

Hi Leon

Thanx for the post.

I think the first problem was the introduction of smartmatch at all without much more discussion. As previously noted - not by me - the pathological set of combinations which triggered specific behaviour was, presumably :-), clear to Damian, but not us journeyman. We didn't ever need that complexity. It should have been introduced with a tiny number of cases handled (e.g. only 'eq'), and when that proved successful, expanded systematically to include other cases. Sigh.

Frankly I refused to use it when I saw the list of combinations. There is no argument based on alleged 'logic' that I will accept. The issue is: How does the average programmer understand the consequences of comparing $a with $b in far too many ways? If the mental load is so great - forget it.

So a major revision is, to me, no problem, as long as the cognitive load is as small as possible.

(I'm posting this without going via Preview because far too many times, and after alleged fixes to the code, I've been auto-expired, and hence lost the text).

Cheers Ron

He Leon

Lastly, yes, the choice of 'whereis and whereso' is so bad it's embarrassing, since they are too close to each other to be obvious /to beginners/.

Hi All

I suppose I should suggest an alternative to 'whereis and whereso'. Literally off the top of my head, because I did not analyse it, I'd say something like case(string) and case(integer) might be better.

Sorry, what's that? It clashed with preexisting code!? Hmm, maybe, perhaps, sort of - but not with quote-less usages of string and integer, right?

Merry Christmatch. Hahaha. Hohoho.

I think the first problem was the introduction of smartmatch at all without much more discussion.

Oh there was no dearth of discussion at the time. And I argued against it strenuously. Nobody seemed to hear, though. 5.10 was the release where p5p tried to implement as much of Perl 6 as possible in Perl 5… almost a decade prematurely. In the end the only thing worth the trouble was //. In most other respects, that release was a disaster.

Frankly I refused to use it when I saw the list of combinations.

RJBS nailed it: “27-way recursive runtime dispatch by operand type”.

And when is even worse than smartmatch itself, it has its whole own extra set of rules on top.

This is an alarmingly bad design decision, but ultimately it doesn't matter. It just adds to the already long list of evidence that the only sane way to write perl is to limit yourself to a 5.8 feature set, as most cpan authors have been doing all along anyway. I sadly can't even think of what you'd be missing out on (the actual examples other than smartmatch that came to mind have actually been removed since my last look).

I wrote up my own thoughts. Aside some the actual language issues I'm most disturbed that this didn't follow the normal experimental feature contract in perlpolicy. Not only that, the feature branch wasn't rebased (another violation) so was enmeshed in what was separately happening in blead. Socially, this change is bad for users and core developers.

I didn't mean there was shortage of commentary, just a shortage of commentary having our desired effect.... Bit like auto-deref, actually :).

Yes, autoderef came to my mind as well.

Maybe documenting some rationale for at least "whereso" would help

It's probably inspired by the so function from Perl 6, which simply coerces its argument to Bool - like the not function but without the negation.

I think that smart match tried to do too much. the use I had for it was "when" to allow for a more flexible "switch" construct than using a mix of "nswitch", "sswitch" and "rswitch" (and variations, as provided by various CPAN modules).

Things like "appearing as a value in an array", and other complexities, would be better accomplished by their own operators or functions.

Leave a comment

About Leon Timmermans

user-pic