Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Why version strings?

by gunzip (Pilgrim)
on Mar 28, 2011 at 14:37 UTC ( [id://895930]=perlquestion: print w/replies, xml ) Need Help??

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

I may be missing something obvious but if I have Perl 5.12 installed why should I have to specify:

use 5.012;

It seems even more absurd with Perl 6:

use v6;

Can't Perl detect which version is installed or something? I've heard the argument that it allows you to switch off features introduced in the latest version but shouldn't it be done the other way round, ie. specify if you want limitations, not to enable what is available by default? I still don't get this one. Why would I bother with Perl 6 at all if I didn't want to "use v6"? If I want to use Perl 5.12 as if it were 5.10 then that is the exception to the rule for which the version string would be relevant, not the other way round.

Replies are listed 'Best First'.
Re: Why version strings?
by Corion (Patriarch) on Mar 28, 2011 at 14:43 UTC

    Specifying the minimum version of Perl needed for your script in your script is like specifying what fuel your car runs on - it allows Perl to exit with a more sensible error message than Syntax error ... when a lower version of Perl is run with your script.

    How would a version 5.10 Perl know about new syntactic features introduced in 5.14?

      How would a version 5.10 Perl know about new syntactic features introduced in 5.14?

      Isn't that rather a case for improving error messages, not imposing a requirement on every single script?

        How would you improve the error messages for Perl 5.6, a version that was last released in 2002 (or something), today?

      I'd rather work out the "Syntax error .." than have to enter the version string in every single piece of Perl that I write. We didn't need it with 5.8 so why now?
        I'd rather work out the "Syntax error .." than have to enter the version string in every single piece of Perl that I write.

        That's your choice. I for one write quite a lot Perl 6 scripts, and thus often actually mix up the versions of the compiler and the language. To me it's incredibly helpful.

        We didn't need it with 5.8 so why now?

        You don't need to. It works fine without.

        It won't give you some new built-in though, because that would break backwards compatiblity with older scripts.

        In general it is a good idea to declare a version, in particular in the light of the faster Perl 5 development process. But of course it's still your choice.

        Don't you have a standard-header you copy to each of your scripts? With use strict, , use warnings; and a copyright-notice? Adding one additonal line specifying the perl-version is no big deal - and nothing to get emotional about ;-)

        All the best, Rata

        It's not all about working out the syntax error, either (even if "you need a newer version of perl" seems much better than some "yada-error in Foo::Bar line 1234").

        With the version string, automated tools can decide which is the newest version of the module they can use on a given installation. One of these tools is cpantesters. For example my Maplat project uses some features of perl 5.12, so it wont work on older perl installations:

        Maplat CPAN Testers results

        The "Pass summary" table gives the potential user a good overview which Maplat version works on which OS and perl version.

        The detail tables gives me as a developer a good overview where the bugs are. It differenciates between NA (not available), PASS and FAIL. This makes it much easier to use my limited time to hunt for real, *new* bugs than having to sort out known incompatibilities.

        Also, if i ever want to backport some modules to older versions of perl (for whatever reasons), i can simply grep through the files for the version string and find the one that are too modern. Works the other way around, too, when a newer version of perl changes/fixes/removes some "experimental" features of the previous version.

Re: Why version strings?
by moritz (Cardinal) on Mar 28, 2011 at 15:38 UTC
    Can't Perl detect which version is installed or something?

    It's not about the perl version being installed. Once you invoke a perl binary, its version is fixed.

    But modern perl versions also have the ability to act like older perls. For example 5.012 has strict implied if you declare that version, but it can also act like an older perl and be non-strict by default.

    Now you could argue that the perl binary should autodetect the version of the script, but that's not possible in the general case. A script can be valid in different versions of perl, and produce different output (I've written such a script for educational purposes.

    So it could only guess, but guessing is very dangerous. And since Perl cannot be parsed without executing it, autodetection could have dangerous side effects.

Re: Why version strings?
by JavaFan (Canon) on Mar 28, 2011 at 16:13 UTC
    I may be missing something obvious but if I have Perl 5.12 installed why should I have to specify:
    use 5.012;
    You are missing that fact that you don't have to.

    Can't Perl detect which version is installed or something?
    No, Perl cannot, but perl can. The point is, use 5.012; appears in the Perl program, and when the perl binary runs, it checks whether its version is at least the version required by the program. If not, the program is terminated with an appropriate message.

    Note that since 5.10, use 5.010; (or later, or using use 5.10.0) there's an implied use feature ':5.10'; (or whatever version number you used). And since 5.12, the use version will enable strict. No enabling of features or strict happen when using require.

    Also note that use v5.10; == use 5.10.0; == 5.010;. But use 5.10; == use 5.100;. Which, IMO, is not very DWIM.

    I don't know whether there's a (single-line) syntax that at compile time checks for 5.10, but which doesn't enable features.

      Also note that use v5.10; == use 5.10.0; == 5.010;. But use 5.10; == use 5.100;. Which, IMO, is not very DWIM.

      An unfortunate side-effect of having two similar but very different numbering systems. At least the error message is useful.

      $ perl -e'use 5.10;' Perl v5.100.0 required (did you mean v5.10.0?)--this is only v5.12.2, +stopped at -e line 1. BEGIN failed--compilation aborted at -e line 1.

      I don't know whether there's a (single-line) syntax that at compile time checks for 5.10, but which doesn't enable features.

      $ perl -M5.014 -e1 Perl v5.14.0 required--this is only v5.12.2, stopped. BEGIN failed--compilation aborted.
        $ perl -M5.014 -e1 Perl v5.14.0 required--this is only v5.12.2, stopped. BEGIN failed--compilation aborted.
        I fail to understand how that answers my question:
        I don't know whether there's a (single-line) syntax that at compile time checks for 5.10, but which doesn't enable features.
        If I substitute 5.010 for 5.014, 5.10 features are enabled:
        $ perl -M5.010 -e 'say "foo"' foo
Re: Why version strings?
by chromatic (Archbishop) on Mar 28, 2011 at 16:54 UTC
    I've heard the argument that it allows you to switch off features introduced in the latest version but shouldn't it be done the other way round, ie. specify if you want limitations, not to enable what is available by default?

    Perl should work that way, but Perl hasn't worked that way in any version of 1 through 5, and so you have a choice to make. Make that change arbitrarily with Perl 5.16 next year and for everyone running code written for earlier versions to edit that code to run on Perl 5.16, or do it the current way and ease upgrading worries.

    (Even so, it's still a good idea to specify the version number of the Perl language against which you've written any program, no matter what Perl 5's behavior regarding default behaviors.)

      Even so, it's still a good idea to specify the version number of the Perl language against which you've written any program

      That's a nice theory. And it sounds so reasonable.

      It is too bad that the feature isn't actually implemented in a reasonable way for that use case. There is no "I wrote this on 5.10.1 so I can't be sure it will work on other versions" feature. There is only the "I'm damn sure that this will never, ever work on 5.10.0 or before and so any prior version will just tell you 'tough shit' with no real explanation" feature.

      Since the 'require/use VERSION' feature has become increasingly misused, it would be nice if that feature became pluggable so, for example, an automated smoke test of 5.8.9 could arrange for "require 5.010.001;" (for example) in a module to be non-fatal in a deterministic way so that the module could actually be tested on 5.8.9 and the test results would actually record either "no, this actually works on 5.8.9; shame on the module author" or "one reason this doesn't work on 5.8.9 is that it uses //".

      It is quite unfortunate that 'use VERSION' doesn't even allow the author to include a reason.

      use 5.010 'uses //'; Perl v5.10.0 required (uses //) -- this is only v5.12.1, stopped. # No, this doesn't actually work.

      Much better to just roll your own reasonable implementation

      BEGIN { die "// not implemented in Perl $]\n" if $] < 5.010 }

      Or even avoid the silly version number BS altogether:

      BEGIN { die "// not implemented in Perl $]\n" if ! eval "undef() // 1" + }

      Well, at least for cases where the existing diagnostic is worse (like this one):

      perl5.8 -e'my $x= undef() // 1;' Search pattern not terminated ...

      Or, for chromatic, it would be:

      use v5.14 "Your Perl is old. Please don't waste my time. Go away until + you upgrade.";

      ...except that hard-coding v5.14 probably seems unfortunate to him. :)

      - tye        

        There is no "I wrote this on 5.10.1 so I can't be sure it will work on other versions" feature.

        Yet.

        There can only be such a feature if sufficient numbers of Perl 5 programmers stop pretending that perl is completely forward and backwards compatible without explicitly including version numbers in all files.

Re: Why version strings?
by ikegami (Patriarch) on Mar 28, 2011 at 18:17 UTC

    If I want to use Perl 5.12 as if it were 5.10 then that is the exception to the rule

    If that's true, you are an exception. Most people expect scripts written before Perl 5.12 was released to still run using perl 5.12 (for example).

    I doubt it's true though. Contrary to what you say, I suspect you're not ok with new versions of Perl breaking your scripts.

    if I have Perl 5.12 installed why should I have to specify: use 5.012;

    You don't have to specify «use 5.012;». You just have to specify «use 5.012;» if you want backwards incompatible features of version 5.12. This enables the language to change without breaking backwards compatibility.

    For example, «use feature qw( say );» (or «use 5.010;» or «use 5.012;») is required to use the say builtin since not requiring it would break the following program:

    sub say { print "foo\n" } say();

      (Not really a “reply” ... oops.)

      “Quirky” though such a notion may seem to be at first blush, there actually is a reason for it, and it is arguably the best-all-around engineering choice that could have been made.

      use versionstring is a pragma which Perl has supported for a very long time.   Both older and newer Perls will understand it, and the older ones will also know to reject5.012.”   External code which knows how to search a source-file for a use versionstring statement, such as CPAN, also will continue to see what it needs to see ... without needing to be upgraded in order to “do the right thing.”

      If you intend to use a new or redefined feature, then of course you will do whatever it takes to do so.   But that’s really not what this application of use is all about.   The goal of this design is to prevent older Perl installations from running into trouble with newer code ... and to prevent newer interpreter versions from doing the wrong thing with older code.   A barrier mechanism had to be devised, such that it would work correctly whether it was included, or (certainly more likely to be the case...) omitted, and that would be backward-compatible.

        I don't see how this relates to the OP at all. He asked why the new features of a language (e.g. say) weren't on by default. He didn't mention or imply any issue with the use of use version; you describe.

Re: Why version strings?
by JavaFan (Canon) on Mar 28, 2011 at 17:38 UTC
    I've heard the argument that it allows you to switch off features introduced in the latest version but shouldn't it be done the other way round, ie. specify if you want limitations, not to enable what is available by default?
    Neither is true.

    First, use 5.XXX; has always had the meaning "your perl binary needs to be at least 5.XXX for the program to run". This could be because the program uses features not available before, or because a bug-fix essential for the correctness of the program happened in 5.XXX.

    Now, since 5.10, use 5.010; also enables some of the new features of 5.10. Most of them you get regardless, whether you have an explicite use 5.010; or not. But a few features have the potential to clash with existing code; say is best known example. The alternative, a policy that's followed up to 5.10 is to not make say part of the language.

    Since 5.12, use 5.012; could also introduce changes in behaviour. I'm not too fond of that - it means that if you take a program that has use 5.012;, and remove it or change it to say, use 5.010;, you don't get compilation errors (what you typically would get if do say "foo" and remove the use 5.010; statement), or even runtime errors. Your program just misbehaves - and it'll be hard to debug.

    And don't say "don't do that". People have slapped on a use 5.XXX for too high versions. I've made 5.8 modules work on 5.6 by just removing the use 5.008;, and even further back by removing use 5.006; to get them working on 5.005. It was always safe to try - you'd get a compilation error if the use 5.006; or use 5.008; was indeed needed.

    Perl never has used use 5.XXX; to impose limitations. The main purpose of use 5.XXX; is to signal "this code will not compile/run correctly on versions before 5.XXX". And you'd still get most of the functionality of 5.12 by just running 5.12, regardless whether you're using use 5.012; or not. (The only things you'll miss out on: say, given/when (but you do get smart match), state, Unicode strings and strict enabled). AFAIK, 5.14 will not introduce new features that aren't enabled by default.

      Since 5.12, use 5.012; could also introduce changes in behaviour. I'm not too fond of that

      Since 5.10, actually. If there was no change in behaviour, there wouldn't be need for the features pragma at all.

      $ perl -e'sub say { print "foo\n"; } say for "bar";' foo $ perl -E'sub say { print "foo\n"; } say for "bar";' bar

      It was always safe to try

      It's no more or less safe to try now as then. By switching use 5.008; for use 5.006;, you could get bugs that changed behaviour and compile-time errors just like you do now.

      Update: Deleted a comment based on something I misread.

Re: Why version strings?
by sundialsvc4 (Abbot) on Mar 28, 2011 at 16:30 UTC

    Like everything else in the software world, Perl is “a work in progress.”   It is constantly evolving and changing, with new features being added and the implementations of older ones being revised.   This produces known incompatibilities with older code ... and known dependencies upon newer versions of Perl.   The compiler might not detect these, because they might not generate “syntax errors” at all:   the code just doesn’t work properly any more.

    Who is the one player in this game who knows this?   You, the programmer.   Only you, who wrote the code or who made the latest changes to it, are in a solid position to know that a dependency exists.   Therefore, you use this statement to inform both Perl and every human who comes after you that the dependency is there.   Now, Perl can enforce it for you.   Pragmatically speaking, “now, the human beings can be aware, probably for the first time, and can take appropriate action and/or make appropriate preparations.”   (If you don’t tell them, how will they know?   The simple answer is, they won’t know, and you will forget.)

    If you attempt to install a package onto an incompatible Perl, Perl can, because it is armed with this information that you have provided, block the attempt.   The human being who is making the attempt might then be prompted to actually read the README file:-) in which you oh-so carefully described the issue...

    And you should describe the issue carefully, because yes, you will forget.   Include built-in POD documentation in the affected modules, in which you very clearly and completely state what version is required and why it is required, and if possible, what will go wrong if such-and-such version is used by mistake.   “Age happens, it rather sneaks up on you, and it sux.”

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others having an uproarious good time at the Monastery: (6)
As of 2024-04-16 08:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found