Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

RFC: Version::Easy

by LanX (Cardinal)
on Jul 10, 2020 at 17:28 UTC ( #11119150=perlmeditation: print w/replies, xml ) Need Help??

Following the discussion in Why eval $version? I'd like to propose the following approach.

Usage

use Version::Easy; $VERSION = 'v1.2.3'; # v-str # or... $VERSION = '1.002003'; # float $VERSION = 'v1.2.3_4'; # v-str + alpha $VERSION = '1.002003_4'; # float + alpha

please note that:

  • Version::Easy adds magic to $VERSION
  • it's also declaring $VERSION in the caller's package, so no our needed
  • all formats like floats or v-strings with optional "_alpha" allowed
  • no boilerplate eval or tr/// needed
  • version is used internally, which is the same mechanism applied by use
  • syntax check at runtime
  • toolchain modules with static parser find "$VERSION" as usual
Implementation:
  • $VERSION is a tied scalar,
  • in STORE the version number is checked for correct syntax
  • in FETCH a version object is returned
  • the version object is overloading all necessary operators
  • for older versions of Perl the implementation could adapt dynamically to sane defaults
  • if the performance impact is too heavy for normal runs, it's possible to limit the costly parts only to run inside the test suite.

Doesn't this solve most (or all) problems???

Please comment! Where does this fail? :)

use strict; use warnings; # -------------------------------------------------- package Version::Easy; use Data::Dump qw/pp dd/; use version; sub import { my $pkg = (caller)[0]; my $version; tie $version, 'Version::Easy::Tie'; no strict 'refs'; *{${pkg}."::VERSION"} = \$version; } # -------------------------------------------------- package Version::Easy::Tie; require Tie::Scalar; our @ISA = qw(Tie::StdScalar); use version qw/is_lax/; sub STORE { my ($self,$value)= @_; warn "IN:\t\t",$value; if ( is_lax($value) ) { $$self = version->parse($value); } else { warn "corrupt VERSION format $value"; } } # BUG? perldoc Tie::Scalar says no TIESCALAR needed sub TIESCALAR { my $class = shift; my $version; return bless \$version, $class; } 1; # -------------------------------------------------- # --- fake already required for 'use' demo BEGIN { $INC{'Version/Easy.pm'} = 1; } # -------------------------------------------------- # # DEMO # # package TST; use Version::Easy; # --------- test v-str $VERSION = 'v1.2.3'; warn "Str:\t" ,$VERSION; warn "Float:\t" ,$VERSION->numify; warn "V-str:\t" ,$VERSION->normal; my $v1 = $VERSION; # --------- test float $VERSION = '1.002003'; warn "Str:\t" ,$VERSION; warn "Float:\t" ,$VERSION->numify; warn "V-str:\t" ,$VERSION->normal; my $v2 = $VERSION; warn "Are both Version equal?:", $v1 == $v2; warn "v-str bigger?:", $v1 > 'v1.2.2'; warn "v-str smaller?:", $v1 < 'v1.2.4'; warn "v-str not smaller?:", $v1 < 'v1.2.2'; # # --------------------------------------------------

-*- mode: compilation; default-directory: "d:/exp/" -*- Compilation started at Fri Jul 10 19:13:58 C:/Perl_524/bin\perl.exe d:/exp/Version_Easy.pl IN: v1.2.3 at d:/exp/Version_Easy.pl line 29. Str: v1.2.3 at d:/exp/Version_Easy.pl line 69. Float: 1.002003 at d:/exp/Version_Easy.pl line 70. V-str: v1.2.3 at d:/exp/Version_Easy.pl line 71. IN: 1.002003 at d:/exp/Version_Easy.pl line 29. Str: 1.002003 at d:/exp/Version_Easy.pl line 78. Float: 1.002003 at d:/exp/Version_Easy.pl line 79. V-str: v1.2.3 at d:/exp/Version_Easy.pl line 80. Are both Version equal?:1 at d:/exp/Version_Easy.pl line 84. v-str bigger?:1 at d:/exp/Version_Easy.pl line 86. v-str smaller?:1 at d:/exp/Version_Easy.pl line 87. v-str not smaller?: at d:/exp/Version_Easy.pl line 88. Compilation finished at Fri Jul 10 19:13:58

Cheers Rolf
(addicted to the Perl Programming Language :)
Wikisyntax for the Monastery

Replies are listed 'Best First'.
Re: RFC: Version::Easy
by tobyink (Canon) on Jul 12, 2020 at 07:08 UTC
      Good point! Thanks :)

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

      PS: this was my 8888 th post so far :)

Re: RFC: Version::Easy
by Haarg (Curate) on Jul 13, 2020 at 11:17 UTC

    You should probably clarify what problems you are actually trying to solve with this approach. The 'Why eval $version?' post is a long thread discussing a variety of issues. Most of the issues regarding version comparisons are handled by perl 5.10. And this doesn't help with the original question proposed in the 'Why eval $version?' post, which was regarding a version extracted by ExtUtils::MakeMaker.

      > You should probably clarify what problems you are actually trying to solve with this approach.

      avoiding boilerplates.

      > The Why eval $version? post is a long thread discussing a variety of issues.

      Indeed, but if there are problems left, they could be solved inside the module.

      > which was regarding a version extracted by ExtUtils::MakeMaker.

      I don't understand, could you please elaborate?

      edit

      "version" like version.pm or like $VERSION?

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        This module would replace the boilerplate of $VERSION =~ tr/_//d; with the new boilerplate of use Version::Easy;. This doesn't seem like a significant improvement, and adds several dependencies. use version; already accomplishes basically the same thing as this module.

        The original question was about a test that was extracting a version number using MM->parse_version. Any tool doing "static" version extraction isn't aided by a module like Version::Easy.

Re: RFC: Version::Easy
by jcb (Vicar) on Jul 12, 2020 at 03:45 UTC

    This is an interesting little bundle of magic, but is use version; our $VERSION = version->declare('VERSION_GOES_HERE'); really that hard to write?

    Similarly, maybe this should go one step farther and accept the version as an argument to import? Then users could write:

    use Version::Easy 'v1.2.3';

    This would abstract the magic $VERSION variable away into an implementation detail.

      use Version::Easy 'v1.2.3';

      This has the disadvantage that static parsers like the PAUSE indexer won't be able to find the version.

      Like I already said and Toby explained, backwards compatibility to static parsers is a crucial issue here, and

      version->declare('VERSION_GOES_HERE')

      would become just another tribal knowledge.

      You'll find $VERSION also documented in hundreds of places, fixing old documentation is one of Perl's biggest mortgages.

      Furthermore could "Version::Easy" be easily bundled into one master module to rule ehm use them all, hence simplifying boilerplates.

      Compare Modern::Perl.

      Of course a built-in feature

      vers v1.2.3;

      might be more elegant, but this could easily be introduced later on top of this semantics once the tool chain is modernized.

      Cheers Rolf
      (addicted to the Perl Programming Language :)
      Wikisyntax for the Monastery

        There's already a built-in version syntax from Perl 5.14 onwards.

        package Foo::Bar 1.23; ...; # or package Foo::Bar 1.23 { ...; }

        And the PAUSE indexer, etc supports it. It's only a problem if you need to support Perl versions earlier than 5.14.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2020-09-19 03:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    If at first I don’t succeed, I …










    Results (114 votes). Check out past polls.

    Notices?