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


in reply to Re: Using a base module with a required version
in thread Using a base module with a required version

Excellent! -- thank you. I tried testing this, but couldn't get a version mis-match to cause a compile time error.

Then I decided to get into the debugger to have a better look at what was going on -- and the debugger issued the expected error right away. I'm not sure why, but I suspect it's the difference between what stage of the preparation the Perl internals got to in each situation. The debugger gets much closer to run-time, hence it triggered the error.

Alex / talexb / Toronto

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

  • Comment on Re^2: Using a base module with a required version

Replies are listed 'Best First'.
Re^3: Using a base module with a required version
by Corion (Patriarch) on Aug 02, 2019 at 18:58 UTC

    Yes, the two statements run at different times, as you found out:

    package November; use base 'Juliet'; # runs at compile time Juliet->VERSION(1.1); # runs at runtime, after November.pm has been pa +rsed completely

    This usually makes little difference as long as November.pm is its own file. If November.pm is loaded later, code from earlier modules will already have run by the time the ->VERSION() call is made.

      I looked at the code for parent, which in most cases should be used instead of base. I'm wondering (since you have been involved in parent) what you think of a parent::versioned that could be invoked like this:

      use parent::versioned 'Foo'; # No version checking. use parent::versioned qw(Foo Bar); # No version checking. use parent::versioned --norequire qw(Foo Bar); # Still no version chec +king. use parent::versioned ['Foo' => 0.23], ['Bar' => 1.5], 'Baz'; # Versio +n checking on Foo and Bar. use parent::versioned --norequire 'Baz', ['Foo' => 0.23]; # Version ch +ecking on Foo.

      Implementation would be really straightforward as a fork off of existing parent (so as not to clutter parent with baggage).

      Hashrefs could be used instead, so that multiple entries could reside within a single hashref, but the array-ref keeps things nicely flat.


      Dave

        Here it is: parent::versioned version 0.002. This link points directly to the initial mainline (non-dev) CPAN release version. It passes the full parent test suite, plus additional tests around the versioning logic. Code test coverage is 100%. Once the CPAN mirrors pick it up this link will be best for long-term use, as it's not tied to a version number: parent::versioned.

        Synopsis:

        use parent::versioned qw(Foo Bar::Baz); # Same as parent.pm # Set minimum versions for Foo and Buzz::Wham dependencies. # But Bar::Baz and Fizz::Bang wont' be version-checked. use parent::versioned ['Foo' => 1.0], qw(Bar::Baz Fizz::Bang), ['Buzz: +:Wham' => 0.25]; # If you're actually using quadruple inheritance, question your decisi +on. # A more common example: use parent::versioned ['My::Parent::Class' => 3.5];

        Version checking happens at compiletime, since it's built into the import() method. Any version failure will throw an exception. Any module that requires version checking should be specified in an array-ref tuple. Multiple tuples may exist, and may be combined with non-version-checked inheritance too.

        It's not in the Perl core, so you'll have to install it using your favorite method. It adds no dependencies besides Perl itself.


        Dave

        I think using array refs would be a good API for that.

        Since parent has basically no reusable moving parts, simply copying the code and modifying it is the best approach.

        I'm reluctant to modify parent itself, as the code is fairly simple as it is and it has the chance of breaking a lot of things.

      You could just BEGIN { Juliet->VERSION('1.1') }