Monday, June 23, 2014

Perl smartmatch : what now ?

Sorry to wake up an old discussion, but ... does anybody have a clear idea of what is going to happen to smartmatch ?

Our team maintains dozens of internal applications and modules containing "given/when" and smartmatch statements. Most of this code was written between 2007 and 2012 -- remember, at that time smartmatch was an official feature, never mentioned as being "experimental", so we happily used it in many places. The reasons for using smartmatch were quite modest :
  • match a scalar against an array
  • match 2 scalars, without a warning when one of the scalars is undef
  • more readable switch statements, thanks to "given/when"
 When 5.18 came out, I was quite worried about the regression of smartmatch to  "experimental" status, but I was confident that things would be settled in 5.20, so I decided not to upgrade (we still use 5.14). Now 5.20 is out .. and nothing has changed about smartmatch, without even a clue about how this is going to evolve.

Our servers cannot easily upgrade to 5.20, because this would throw warnings all over the place. I tried to find a way to globally turn off these warnings (like set PERL5OPT=-M-warnings=experimental::smartmatch, or  PERL5OPT=-M=experimental::smartmatch), but this doesn't work because the "no warnings" pragma is lexically scoped, so global settings are not taken into account.

So my options are :
  1. don't change anything, don't upgrade, and wait for 5.22, hoping that some reasonable form of smartmatch will be reintroduced into the core
  2. revise all source files, adding a line "use experimental qw/smartmatch/;" at the beginning of each lexical scope ... but I have no guarantee that this will still work in future versions
  3. revise all source files, removing the given/when/smartmatch statements and replacing them with plain old Perl, or with features from some CPAN modules like match::smart or Smart::Match ... but it would be a pity to engage in such work if regular smartmatch comes back in a future version of Perl.
As you can see, none of these options is really satisfactory, so I would be interested in hearing if other companies are in the same situation and how they decided to handle it.

By the way, I love the new Perl way of introducing new features as "experimental", until they become stable and official ... but this only works well when the experimental status is declared from the start. The problem with smartmatch is that it had been official for several years, before being retrograted to experimental. Agreed, the full semantics of smartmatch as published in 10.0 had inconsistencies, but throwing away the whole thing is a bit too harsh -- I'm sure that many users like me would be happy with a reasonable subset of rules for matching common cases.
  
Thanks in advance, Laurent Dami
 

13 comments:

  1. I think this might be a good question to pose on the perl5porters mailing list.

    ReplyDelete
  2. You might also like Switch::Plain

    ReplyDelete
  3. yes, I totally cann't accept this change as a common user!

    ReplyDelete
  4. I changed my code from

    if ($x ~~ @a)

    to

    use List::AllUtils qw(any);
    if (any { $_ eq $x } @a)

    ReplyDelete
    Replies
    1. Why should I use List::AllUtils=any for this case?

      Is it better than `if (grep { $_ eq $x } @a )` ?

      Delete
    2. grep will always iterate through the entire list given. any will stop as soon as it finds a single element matching the condition, which means on average it only has to iterate through half the elements.

      Delete
    3. But I can't find it in docs. Sources clarify this.

      Delete
  5. Thanks LeoNerd. Switch::Plain is very cool, as are lots of other things on https://metacpan.org/author/MAUKE ...

    ReplyDelete
  6. Hey, I'm in the same boat, I've been using smartmatch for switch since appearance and I like it, it works for me. The way i deal with pragmas is that i centralize them in a custom minipackage, as in "package pragmas" and I import that, so it's easier to manage "slight incompatibilities" like these. So when p5p marked it as experimental and issued a warning for it, i just put warnings->unimport( 'experimental::smartmatch' ) if $] >= 5.018; right below the "usual" warnings->import( FATAL => 'all' ); If p5p will would rip it off entirely, I'll just fetch some variant from cpan, put it in the pragmas package and import it from there, transparently. It's annoying, but it's not p5p's responsibility to update my code, if I wanna keep up with all the goodies and advancements. Otherwise you keep the code "dead", stuck on 5.14 and that's that, it works.

    ReplyDelete
  7. Hi we had the same issue with pseudhashes which was an official feature until 5.10
    The problem was that old systems had huge databases with old storables containing pseudohashes. there was no way

    I had to write a module to serialize pseudohashes structures into plain hashes, and we then saved as hashed structured when they appreared.
    Or just leave them unitl all nodes in a cluster was uploaded from the perl 5.8.9.

    You have to live with it, just write software that adopts.

    ReplyDelete
  8. Hello, I may be ressurect an old post, but as written here ( http://perldoc.perl.org/perl5180delta.html#The-smartmatch-family-of-features-are-now-experimental ), it is possible to stop the warning with this command:

    no if $] >= 5.018, warnings => "experimental::smartmatch";

    This will may be useful for others ^^'.

    ReplyDelete
  9. Well, 5.22 is out. Has ANYTHING happened in this area?
    Does anyone know how to suppress the warnings globally
    (eg with an envar) ?

    ReplyDelete