Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Conditionally executing different code based on Perl Version

by dlarochelle (Sexton)
on Feb 21, 2012 at 21:32 UTC ( #955395=perlquestion: print w/ replies, xml ) Need Help??
dlarochelle has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to upgrade some code to run correctly in Perl 5.14. However, I still need it to work in older version of perl.

I would like to have certain code execute only if Perl 5.14 is detected. Essentially I'm looking for something similar to the #if  MACRO #endif construct in C.

My specific use case is that I need use re '/d'; in order for some existing regular expressions to want with 5.14 but earlier Perl versions will give a compile error if I add this pragma.

I've searched extensively but I haven't found any information for how to do something like this. So any suggestions would be greatly appreciated.

Thanks in advance

Comment on Conditionally executing different code based on Perl Version
Download Code
Re: Conditionally executing different code based on Perl Version
by Eliya (Vicar) on Feb 21, 2012 at 21:50 UTC

    You can check the special variable $], e.g.

    use if $] >= 5.014, re => '/d';

    See also the module if.

    (Yes, the docs say "deprecated in Perl 5.6", but it still works more than a decade later :)

      I loaded perlvar.pod into my editor to submit a patch to remove the deprecated notice, but it was already gone! 5.16 won't have that deprecated notice.

Re: Conditionally executing different code based on Perl Version
by tobyink (Abbot) on Feb 21, 2012 at 22:05 UTC

    The previous answer should work nicely for your particular case. For the more general case,

    if ($] >= 5.014) { ... } else { ... }

    will often work. However, in some cases you'll have code that while OK in one version of Perl, will result in a compile-time error in another. In those cases, you may need to protect Perl from your code using a stringy eval, or placing the code in external files and conditionally requireing them.

    The $] >= 5.014 can probably be optimized by declaring a constant at BEGIN time:

    BEGIN { *NEW_PERL = ($] >= 5.014) ? sub(){1} : sub(){0}; } ... if (NEW_PERL) { ... } else { ... }

      Thanks Eliya and tobyink.

      This is exactly what I was looking for!

      Note that none of your suggestions actually works for the OP. He cannot use use re '/d'; in code that's compiled under 5.12 or earlier, and since its effect is scope based, putting it inside an eval isn't going to help either, as an eval creates its own scope.

      What may work is:

      require re; re->import('/d') if $] >= 5.014;
      but I have not tested this.
Re: Conditionally executing different code based on Perl Version
by ikegami (Pope) on Feb 21, 2012 at 22:57 UTC

    By the way, it's not «use re "/d/";»; it's «use re "/d";» (as in /.../d).

      Thanks I've updated the post
Re: Conditionally executing different code based on Perl Version
by JavaFan (Canon) on Feb 22, 2012 at 08:37 UTC
    I'm trying to upgrade some code to run correctly in Perl 5.14. However, I still need it to work in older version of perl.

    I would like to have certain code execute only if Perl 5.14 is detected. Essentially I'm looking for something similar to the #if MACRO #endif construct in C.

    My specific use case is that I need use re '/d/'; in order for some existing regular expressions to want with 5.14 but earlier Perl versions will give a compile error if I add this pragma.

    Considering that /d is the default, why even bother? If you aren't using use re '/l'; or use re '/u'; in an outer scope, there's no need to do use re '/d'; in an inner. Quoting from perlre:
    If none of the above apply, for backwards compatibility reasons, the "/d" modifier is the one in effect by default. As this can lead to unexpected results, it is best to specify which other rule set should be used.
      Considering that /d is the default, why even bother? If you aren't using use re '/l'; or use re '/u'; in an outer scope, there's no need to do use re '/d'; in an inner. Quoting from perlre:
      If none of the above apply, for backwards compatibility reasons, the "/d" modifier is the one in effect by default. As this can lead to unexpected results, it is best to specify which other rule set should be used.
      Good question. It turns out that the default is different if the code has 'use locale' and this code did:

      The use re '/foo' pragma can be used to set default modifiers (including these) for regular expressions compiled within its scope. This pragma has precedence over the other pragmas listed below that change the defaults.

      Otherwise, use locale sets the default modifier to /l ; and use feature 'unicode_strings or use VERSION (or higher) set the default to /u when not in the same scope as either use locale or use bytes. Unlike the mechanisms mentioned above, these affect operations besides regular expressions pattern matching, and so give more consistent results with other operators, including using \U , \l , etc. in substitution replacements.

      If none of the above apply, for backwards compatibility reasons, the /d modifier is the one in effect by default. As this can lead to unexpected results, it is best to specify which other rule set should be used.

      So for code with 'use locale' the default regex behavior changed from 5.12 to 5.14.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://955395]
Approved by Eliya
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (13)
As of 2014-07-24 19:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (165 votes), past polls