http://qs321.pair.com?node_id=1166630

cheselton has asked for the wisdom of the Perl Monks concerning the following question:

I've been using the use feature qw( switch ) feature, pretty much since in came out in Perl 5.10. As of v5.18 or so, someone with enough clout, decided that the "smartmatch" feature was experimental, and this given/when construct appears to fall into the "smartmatch" category. Normally this isn't an issue, as I'm usually writing one-off scripts that tackle a specific task and/or run on identical platforms -- so the same Perl version all around. I'm currently working on a project that crosses different linux distributions, and therefore different Perl versions. Some (one, actually) before 5.18 and some (most) after (5.20 or so). The older ones run fine; the newer ones complain that the feature is "experimental". One can disable the warnings on the newer perls by using... no warnings "smartmatch::expierimental;...but the older perls don't recognize the pragma and fail to run. So what's the best way to use this case/switch functionality across perl versions without editing my code every time? (Note: I've tried the Switch module, but it doesn't seem to handle regular expressions very well -- especially with nested blocks.) Any help appreciated. TIA

Replies are listed 'Best First'.
Re: Best option for "switch/case" functionality?
by haukex (Archbishop) on Jun 27, 2016 at 08:19 UTC

    Hi cheselton,

    The easiest way to get rid of the warning on all Perls v5.10 and above is the following, taken from here, which also briefly explains the rationale for making it experimental:

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

    And I think the best way to enable the smartmatch feature is use 5.010_001; (see "Feature Bundles" and the section following it, "Implicit Loading"). I suggest Perl v5.10.1 because there were some significant changes to the way smartmatching and given/when works.

    Update: I should add that because of its experimental state and the fact that the behaviour might change later, I now avoid given/when and use if/elsif or one of the other alternatives like dispatch tables instead. In fact, I sometimes begin Perl scripts with the somewhat clumsy use 5.010; no feature 'switch'; when I want to have v5.10 as my minimum version but want to avoid accidentally using given/when.

    There's also been several discussions here on PerlMonks, for example Bring back the smartmatch operator (but with sane semantics this time)!, which includes this post listing some of the alternatives available on CPAN. Hopefully we will get back a working given/when someday :-)

    Hope this helps,
    -- Hauke D

    Update: Expanded post slightly. Yet Another Update: Used ge rather than >= as explained here.

Re: Best option for "switch/case" functionality?
by hippo (Bishop) on Jun 27, 2016 at 08:16 UTC

    "Best" is subjective but the FAQ gives a number of alternatives for given/when. Hopefully one of those appeals to you.

Re: Best option for "switch/case" functionality?
by TheDamian (Vicar) on Jun 27, 2016 at 11:33 UTC

    Grab the experimental.pm module from CPAN (or you may already have it if you have a recent version of Perl installed).

    Then, at the top of each file add:

    use experimental 'switch';

    Then continue to use given/when under every version of Perl that supports it...without annoying warnings or meta-warnings.

Re: Best option for "switch/case" functionality?
by BrowserUk (Patriarch) on Jun 27, 2016 at 20:28 UTC

    A hash of coderefs is perfect if your cases are all constants, but if you want something that is closer to Switch or given/when, without the headaches, take a look at Dan Brook's Switch::Perlish which allows (for example) a coderef against a hash, or a regex against an array, and many more combinations; but with clear and sane rules about what each combination does.

    It's what given/when with smart matching could have been; but with slightly more cumbersome, but still eminently readable syntax.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
      I provided a patch for the module to work on 5.14+. Thanks for pointing me to an interesting module.

      ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,

        Looking at the module it doesn't seem to have been maintained since 2006. And (if memory serves) Dan Brook's PM handle was broquaint, which hasn't been logged into since 2013.

        So, whether your patch will get applied...


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice. Not understood.
Re: Best option for "switch/case" functionality?
by talexb (Chancellor) on Jun 27, 2016 at 20:04 UTC

    As brother perlfan has already mentioned, using a hash is a great way to solve this: if the choice has a hash entry (exists), then you call the appropriate anonymous sub; otherwise, you handle the default case.

    Alternatively, if you want to handle cases in a specific order (perhaps you want the most likely case first?), you can arrange the list as an array, then just walk through the array.

    The great thing about either of these approaches is that the code is really easy to implement, it's very flexible, and I think it's nicely self-documenting.

    Alex / talexb / Toronto

    Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

Re: Best option for "switch/case" functionality?
by perlfan (Vicar) on Jun 27, 2016 at 19:40 UTC
    If your cases don't need to be evaluated conditionally, I like to use a hashref:
    my $dispatch = { option1 => sub { print "opt 1\n"}, option2 => sub { print "opt 2\n"}, option3 => sub { print "opt 3\n"}, default => sub { print "default\n" }, }; $dispatch->{($dispatch->{$option})?$option:'default'}->(@args);
    YMMV,
Re: Best option for "switch/case" functionality?
by cheselton (Novice) on Jun 27, 2016 at 22:48 UTC

    Thanks for all of your posts and wonderful insights. I think I may have worded my request in such a way that it put focus on the wrong issue: the warnings for using the feature.

    When the issue I was actually hoping to get addressed, more specifically, was that perls <5.18 didn't recognize the "experimental::smartmatch" and would throw a compile-time error. This prevented the script from even running to throw warnings or anything else.

    I think haukex inadvertently came across the solution as no if $] ge '5.018', warnings => "experimental::smartmatch"; seems to work fine. What I was using (use warnings;\nno warnings "experimental::smartmatch";) threw the error. I guess the seemingly minor difference in syntax solves the issue.

      Rather than hard-code the "magic number"` '5.018', I'd go with

      BEGIN { eval { require warnings; warnings->unimport('experimental::sma +rtmatch') } }

      - tye        

        Isn't that lexical to the BEGIN{} block?