Ricardo is pushing for smart match changes.

A long time ago, Ricardo suggested big changes to smart matching. I added my thoughts on how that does not benefit Perl. Now he's pushing for those changes again.

This sort of change should be important to all Perl users. We already have two versions of smart match out there so you have to be careful with your Perl versions. This would add a third. I don't think these changes are in the interests of most users, and unless ordinary users pay attention, they'll get whatever p5p decides to give them.

Jesse Vincent proposed moving all smart match changes out to pragmas so you could know which one you would get. He also suggested that new features come in as pragmas before they make it into core.

13 Comments

This sort of change is indeed important to all Perl users. It is a misfeature at this point that needs to be corrected. The current semantics are not at all consistent and definitely broken between 5.10 and 5.12. I would be /really/ surprised after getting burned with that change that there are many users of smart match left. The thing is, if a feature is broken, is it supposed to remain static after one attempt is made to fix it? I would argue no.

The simplification of smart match that Rik is proposing is sane, consistent, and takes a lot of the surprise out of the feature. And it would keep smart match in the core rather than moving it to a pragma ghetto. Seems like a win to me.

What users that were burned by the first change wouldn't be interested in an actually working feature? Those users have already demonstrated that they want the feature. Fixing it to work consistently would indeed be in those user's interests.

And if those users don't want those fixes, they are more than welcome to join the conversation on p5p. Having a decentralized conversation across a multitude of blogs, tweets, etc. doesn't help convey those wishes and desires to the people that have the tuits to do this work. It isn't a matter of "they'll get whatever p5p decides to give them." It really is: "The hackers that work on core think this is a great idea and no one is telling them otherwise in the forum those hackers use." Silence is tacit consent and all that.


A long time ago, Ricardo suggested big changes to smart matching. I added my thoughts on how that does not benefit Perl. Now he's pushing for those changes again.
Is it really necessary to make this personal. This is not just Ricardo's thing, you're misrepresenting the situation and that's really not fair to him. There is a broad consensus that the current system is wrong and broken. For that matter, Ricardo is more conservative than many others who advocate removing it altogether. We need to find a way to deal with this, but pointing fingers really isn't going to help with that.
Jesse Vincent proposed moving all smart match changes out to pragmas so you could know which one you would get. He also suggested that new features come in as pragmas before they make it into core.
In this case, that will be of only limited use. If you want matcher libraries, you do not want lexical semantics. You actively need the the caller's semantics.

As I understand it, the smart match pragma suggestion is not to remove smart match from core, but to allow users to specify which "version" of smart match they want using a lexical pragma. The ~~ operator would just become syntactic sugar for whatever match module was currently in effect. (Like how <*.txt> is currently a hook for File::Glob::glob("*.txt").)

That seems like a sensible solution to me, provided that the default smart match implementation (in absence of loading a particular pragma, or use VERSION) is backwards compatible. Personally my ideal smart match operator would be:

$a        $b          equiv to
-----------------------------------------------
Any       Undef       !defined $a
Any       Simple      $a eq $b
Any       Regexp      $a =~ $b
Any       Code        $b->($a)
Any       Object      $b->overloaded_method($a)
Any       Array       !!(grep { $a ~~ $_ } @$b)

The Array case would have short-circuiting; the Object case would throw if the object didn't overload smart matching.

This is roughly a subset of the current behaviour (with the exception of the Num gotcha in the current implementation), and tends to be how I use smart match in practice. It's also roughly the same as Ricardo's version, but adds Any~~Array and makes the behaviour of smart match entirely dependent on the right hand side (i.e. $b).

This also goes hand-in hand with my suggestion that MooseX::Types::TypeDecorator ought to overload ~~, enabling the ability to do things like:

use MooseX::Types::Moose qw(ArrayRef Num);
my @nums = get_number_list();
die "non-numeric" unless @nums ~~ ArrayRef[Num];

I'm actually of the opinion that it would be quite positive for the Perl community. Right now, smartmatching, and given/when by extension, are surprising, confusing and way too complex. Which leads to nobody really using it.

I can't use it without looking at the documentation for a while, And even then I'm not sure I've gotten it right. The new proposal is the smartmatch I always wish i had. And so I fully support the change.

BTW, as I understand it, smart match was stolen from Ruby. For anyone following Ruby development, was/is this feature equally controversial to Ruby users?

Anyway, as a Perl user, I have only used Scalar ~~ Array(ref), a.k.a. for "in". Never used given/when, and does not plan to.

Very few Perl programmers actively follow p5p. So I'm glad to see major issues brought to the greater community through blogs or elsewhere.

Having a decentralized conversation across a multitude of blogs, tweets, etc. doesn't help convey those wishes and desires to the people that have the tuits to do this work.
This is probably true, so perhaps this blog post can be a call to action: "If you want to weigh in on this, head on over to p5p..."

Keeping the conversation in one centralized location (p5p) is fine - but plaster every wall in every venue with signs pointing back to the conversation when it's a big one, about which the larger community might have valuable input.

I certainly didn't see anything here to take personally!

As regards p5p or not p5p: I really wouldn't wish it upon anybody to have to read any more of p5p than he or she really wants to. There's a lot of it, much of it boring or obscure. Shouting loud in a public place, "Hey, they're talking about something you probably care about!" when there's something clearly important going on is a really good idea.

I do hope that anybody who wants to bring their argument to the table to support or argue against the changes does come post on p5p, where these kinds of discussions can be had in one place. It's not really practical to have the actual debate of the issues spread across "the blogs." I try to keep up with what's getting posted on the ones I know about, but it's hard. I do read every message to p5p, though. :)

(p5p certainly is "in public." It's published in many places and anybody can join and post.)

The problem with making smartmatch behavior a pragma is, as Leon said, that pragmata generally work lexically, and this behavior is something we'd want to be changing based on the caller. Would swapping ~~ behaviors out with a dynamic pragma work? I don't know. I think it starts to make things difficult to follow.

For some more on the difficulties with implementing ~~ behavior with pragmata, see this thread from p5p, in which Jesse L. began work on it and then ran into the problem described:

http://markmail.org/message/ixo3gfqntfi4u34v

I think the case for dynamic scoping is being overstated. If I write a module along the lines of:

package Answers;
use smartmatch 'core';
use Sub::Exporter -setup => {
  exports => [qw( is_affirmative is_negative )],
};
sub is_affirmative {
  lc( $_[0] ) ~~ qw( yes si oui );
}
sub is_negative {
  lc( $_[0] ) ~~ qw( no non );
}
1;

The fact that is_affirmative and is_negative use smart match internally are just implementation details. Somebody who imports the functions into their namespace won't necessarily know that, so it would be pretty odd if their choice of smart match behaviour affected the workings of the is_affirmative and is_negative functions.

Yes, there are cases where you want to use your caller's choice of smart matching algorithm, such as the junctions example, where you might wish to define an any function such that any(1, 2, 3) will use numeric or string matching depending on the smart match algorithm in use by the caller. But that seems to me to be the exception rather than the rule. It could be handled by:

use smartmatch 'caller';

Richardo, thanks for the proposal, and Brian, thanks for highlighting an important issue for broader community input.

Ricardo's proposal looked like a reasonable simplification to me.

For some perspective, I was only able to recently get our production system upgraded from Perl 5.8 to Perl 5.14. We haven't even started to use smart matching in our code yet. I imagine a lot of people are in the same boat. There's no better time to get it right than now.

With a positive outlook on growth, there will be more than double the users are smart match going forward than their all currently (due to those who haven't been able to upgrade plus new adoptions). Thus, it's better target that market, who doesn't care about backcompat.

I maintain some modules that suffer from too much backwards compatibility. Sometimes prioritizing the future instead of the past is a better choice.

I'm not aware of Ruby having smart match? AFAIK Perl5 stole this directly from Perl6: http://perlcabal.org/syn/S03.html#Smart_matching

/I3az/

You just prompted me to make my first ever post to p5p. I don't actively follow it (thanks, Mark Allen for the summaries!), but I will for a while in case my post draws any replies.

Leave a comment

About brian d foy

user-pic I'm the author of Mastering Perl, and the co-author of Learning Perl (6th Edition), Intermediate Perl, Programming Perl (4th Edition) and Effective Perl Programming (2nd Edition).