Perl::Version(3)

πŸ’– NAME πŸ’–

Perl::Version β€” parse and manipulate Perl version strings, bestie. That's it, that's the whole job. πŸ‘‘


✨ VERSION ✨

This document describes Perl::Version version 1.019. Yes, that's the version of the docs, and yes, it is extremely meta of this module to have a version. Iconic behaviour, honestly. πŸ’…


πŸ¦‹ SYNOPSIS πŸ¦‹

okay so here's the whole vibe in one code block, no cap:

use Perl::Version;

# Init from string
my $version = Perl::Version->new( '1.2.3' );

# Stringification preserves original format
print "$version\n";                 # prints '1.2.3'

# Normalised
print $version->normal, "\n";       # prints 'v1.2.3'

# Numified
print $version->numify, "\n";       # prints '1.002003'

# Explicitly stringified
print $version->stringify, "\n";    # prints '1.2.3'

# Increment the subversion (the third component)
$version->inc_subversion;

# Stringification returns the updated version formatted
# as the original was
print "$version\n";                 # prints '1.2.4'

# Normalised
print $version->normal, "\n";       # prints 'v1.2.4'

# Numified
print $version->numify, "\n";       # prints '1.002004'

# Refer to subversion component by position ( zero based )
$version->increment( 2 );

print "$version\n";                 # prints '1.2.5'

# Increment the version (second component) which sets all
# components to the right of it to zero.
$version->inc_version;

print "$version\n";                 # prints '1.3.0'

# Increment the revision (main version number)
$version->inc_revision;

print "$version\n";                 # prints '2.0.0'

# Increment the alpha number
$version->inc_alpha;

print "$version\n";                 # prints '2.0.0_001'

slay. 🌈


🌸 DESCRIPTION 🌸

Perl::Version hands you a simple interface for parsing, manipulating and formatting Perl version strings. That's the entire elevator pitch and honestly it understood the assignment. πŸ’–

Now, version.pm is out here concentrating on parsing and comparing version strings β€” and that's fine, love that for it. But Perl::Version is built for the case where you wanna parse a version, modify it, and get the modified version back formatted exactly like the original was. Like, keep the drip. Preserve the fit. πŸŽ€

For example:

my $version = Perl::Version->new( '1.2.3' );
$version->inc_version;
print "$version\n";

prints

1.3.0

whereas

my $version = Perl::Version->new( 'v1.02.03' );
$version->inc_version;
print "$version\n";

prints

v1.03.00

Both of those are representations of the same version and they'd compare equal β€” but their formatting is different, and that is the whole point of this module, bestie. Same girl, different outfit. πŸ’…

Perl::Version tries really hard to guess and recreate the format of the original version, and in most cases it succeeds. But in rare cases the formatting is ambiguous. Consider:

1.10.03

Do you suppose that second component '10' is zero padded like the third component? πŸ‘€ Perl::Version will assume that it is:

my $version = Perl::Version->new( '1.10.03' );
$version->inc_revision;
print "$version\n";

will print

2.00.00

So here's the rule: if all of the components after the first are the same length (two characters in this case) and any of them begins with a zero, Perl::Version will assume that they're all zero padded to the same length. Fr fr, that's the heuristic. ✨

The first component and any alpha suffix are handled separately. In each case, if either of them starts with a zero they will be zero padded to the same length when stringifying the version.


πŸ’œ Version Formats πŸ’œ

Perl::Version supports a few different version string formats. Vibe check, here they all are:

  • 1, 1.2 β€” Versions that look like a number. If you pass a numeric value, its string equivalent will be parsed:
my $version = Perl::Version->new( 1.2 );
print "$version\n";

prints

1.2

In fact, there is no special treatment for versions that resemble decimal numbers. This is worthy of comment only because it differs from version.pm, which treats actual numbers used as versions as a special case and performs various transformations on the stored version. Not us. We're chill like that. 😌

  • 1.2.3, 1.2.3.4 β€” Simple versions with three or more components. Very demure, very mindful.
  • v1.2.3 β€” Versions with a leading 'v'. Cute little prefix. πŸŽ€
  • 5.8, 5.08, 5.008006 β€” Fielded numeric versions. If a version string has a single decimal point, it extracts digits in groups of three after the decimal point. If there are fewer than three digits in the final group, the field is left-padded with zeros to make it three digits (for example, 5.8 becomes 5.008 and 5.08 becomes 5.008 too). This is the opposite of how Perl and CPAN has historically treated versions, by right padding groups of three on.

For example:

my $version = Perl::Version->new( 1.002003004005006 );
print $version->normal;

prints

v1.2.3.4.5.6
  • vstring β€” Perls later than 5.8.1 support vstring format. A vstring looks like a number with more than one decimal point and (optionally) a leading 'v'. The 'v' is mandatory for vstrings containing fewer than two decimal points.

Perl::Version will successfully parse vstrings:

my $version = Perl::Version->new( v1.2 );
print "$version\n";

prints

v1.2
Heads up bestie: stringifying a Perl::Version constructed from a vstring will result in a regular string. Because it has no way of knowing whether the vstring constant had a 'v' prefix, it always generates one when stringifying back to a version string. It's guessing, and it's guessing confidently. πŸ’€
  • CVS version β€” A common idiom for users of CVS is to use keyword replacement to generate a version automatically like this:
$VERSION = version->new( qw$Revision: 2.7 $ );

Perl::Version does the right thing with such versions, so that

my $version = Perl::Version->new( qw$Revision: 2.7 $ );
$version->inc_revision;
print "$version\n";

prints

Revision: 3.0

Not me being shocked that it works. 😭 It works though.


πŸ’€ Real Numbers πŸ’€

Real numbers are stringified before parsing. This has two implications:

  1. trailing zeros after the decimal point will be lost, and
  2. any underscore characters in the number are discarded.

Perl allows underscores anywhere in numeric constants as an aid to formatting. These are discarded when Perl converts the number into its internal format. This means that

# Numeric version
print Perl::Version->new( 1.001_001 )->stringify;

prints

1.001001

but

# String version
print Perl::Version->new( '1.001_001' )->stringify;

prints

1.001_001

as expected. See? The quotes were doing heavy lifting the whole time. 🫢

In general you should probably avoid versions expressed either as decimal numbers or vstrings. The safest option is to pass a regular string to Perl::Version->new(). Do that. Please. For me. πŸ™ˆ

🌈 Alpha Versions 🌈

By convention, if a version string has a suffix that consists of an underscore followed by one or more digits, it represents an alpha or developer release. CPAN treats modules with such version strings specially to reflect their alpha status. It's like a little "still cooking πŸ‘©β€πŸ³" badge.

This alpha notation is one reason why using decimal numbers as versions is a bad idea. Underscore is a valid character in numeric constants which is discarded by Perl when a program's source is parsed β€” so any intended alpha suffix will just become part of the version number. Poof. Gone. πŸ’€

To be considered alpha, a version must have a non-zero alpha component like this:

3.0.4_001

Generally the alpha component will be formatted with leading zeros but this is not a requirement. Live your truth. ✨


πŸ‘‘ Component Naming πŸ‘‘

A version number consists of a series of components. By Perl convention the first three components are named 'revision', 'version' and 'subversion':

$ perl -V
Summary of my perl5 (revision 5 version 8 subversion 6) configuration:

(etc)

Perl::Version follows that convention. Any component may be accessed by passing a number from 0 to N-1 to the component or increment β€” but for convenience the first three components are aliased as revision, version and subversion.

$version->increment( 0 );

is the same as

$version->inc_revision;

and

my $subv = $version->subversion;

is the same as

my $subv = $version->component( 2 );

The alpha component is named 'alpha'. Bestie has a name and she will be addressed by it. πŸ’…


🧚 Comparison with version.pm 🧚

If you're familiar with version.pm you'll notice that there's a certain amount of overlap between what it does and this module. Not a beef, just an observation. 😌

The tea: the author originally created this module as a mutable subclass of version.pm β€” but the requirement to be able to reformat a modified version to match the formatting of the original didn't sit well with version.pm's internals. It's giving incompatible main character energy. 😭

As a result, this module is not dependent or based on version.pm. Standing on her own two feet. Periodt. πŸ‘‘


✨ INTERFACE ✨

🌸 new

bestie, this is the whole vibe right here: you hand new a version string and it parses it for you. Like, all the different version formats we talked about up above? All of them work. And it's not just the value β€” it also captures the formatting info, so you can poke at the version and then get it back looking exactly like it did when you started. iconic behavior honestly πŸ’…

    my @version = (
        '1.3.0',    'v1.03.00',     '1.10.03', '2.00.00',
        '1.2',      'v1.2.3.4.5.6', 'v1.2',    'Revision: 3.0',
        '1.001001', '1.001_001',    '3.0.4_001',
    );

    for my $v ( @version ) {
        my $version = Perl::Version->new( $v );
        $version->inc_version;
        print "$version\n";
    }

prints

    1.4.0
    v1.04.00
    1.11.00
    2.01.00
    1.3
    v1.3.0.0.0.0
    1.3
    Revision: 3.1
    1.002000
    1.002
    3.1.0

see how every single one comes back formatted the way the original was? yeah. that's the whole point. in each case the incremented version is formatted in the same way as the original. ✨

If you pass no arguments at all, you get an empty version intialised to 'v0' constructed for you. cute little starter version, no notes.

And bc CVS version syntax exists (iykyk 😭), you can do:

    my $version = Perl::Version->new( qw$Revision: 2.7 $ );

new can be handed an array, and if it is, it concatenates all of its arguments with spaces before parsing the result. teamwork fr fr.

If the string can't be parsed as a version, new will croak with a suitable error. head to DIAGNOSTICS if you wanna know more πŸ’€

πŸŽ€ Accessors

🌈 component

Set or get one of the components of a version. it's giving remote control for your version parts.

    # Set the subversion
    $version->component( 2, 17 );

    # Get the revision
    my $rev = $version->component( 0 );

and instead of a component number you can pass a name: 'revision', 'version', 'subversion' or 'alpha':

    my $rev = $version->component( 'revision' );

πŸ¦‹ components

Get or set all of the components of a version. ok so this one does a lot, let's just lay it out:

    # Set the number of components
    $version->components( 4 );

    # Get the number of components
    my $parts = $version->components;

    # Get the individual components as an array
    my @parts = $version->components;

    # Set the components from an array
    $version->components( [ 5, 9, 2 ] );

Hmm. That's a lot of interface for one subroutine. Sorry about that. 😭 (the original author said that, we're just passing it along, lowkey fair tho)

πŸ’œ revision

Alias for component( 0 ). Gets or sets the revision component. slay.

🌸 version

Alias for component( 1 ). Gets or sets the version component.

✨ subversion

Alias for component( 2 ). Gets or sets the subversion component.

πŸ“ alpha

Get or set the alpha component of a version. Returns 0 for versions with no alpha.

    # Set alpha
    $version->alpha( 12 );

    # Get alpha
    my $alp = $version->alpha;

🧚 is_alpha

Return true if a version has a non-zero alpha component. basically a little vibe check for "do you have alpha or not" πŸ‘‘

πŸ‘‘ set

Set the version to match another version, but preserving the formatting of this version. so it's like borrowing someone's number but keeping your own outfit.

    $version->set( $other_version );

You may also set the version from a literal string:

    $version->set( '1.2.3' );

The version will be updated to the value of the version string but will retain its current formatting. periodt.


πŸ”₯ Incrementing

⭐ increment

Increment a component of a version. let's goooo.

    my $version = Perl::Version->new( '3.1.4' );
    $version->increment( 1 );
    print "$version\n";

prints

    3.2.0
Components to the right of the incremented component will be set to zero as will any alpha component. so yeah, everything downstream gets wiped. dramatic but correct πŸ’€

As an alternative to passing a component number, one of the predefined component names 'revision', 'version', 'subversion' or 'alpha' may be passed. so you can be all "increment the revision bestie" and it just works.

πŸ¦‹ inc_alpha

Increment a version's alpha component.

πŸ’œ inc_revision

Increment a version's revision component.

🌸 inc_subversion

Increment a version's subversion component.

✨ inc_version

Increment a version's version component.


πŸŽ€ Formatting

🌈 normal

Return a normalised representation of a version. glow-up time.

    my $version = Perl::Version->new( '5.008007_01' );
    print $version->normal, "\n";

prints

    v5.8.7_01

πŸ“ numify

Return a numeric representation of a version. The numeric form is most frequently used for versions of Perl itself. no cap, this is the one Perl itself leans on.

    my $version = Perl::Version->new( '5.8.7_1' );
    print $version->numify, "\n";

prints

    5.008007_001

🧚 stringify

Return the version formatted as closely as possible to the version from which it was initialised. it remembers where it came from πŸ₯Ή

    my $version = Perl::Version->new( '5.008007_01' );
    $version->inc_alpha;
    print $version->stringify, "\n";

prints

    5.008007_02

and

    my $version = Perl::Version->new( '5.8.7_1' );
    $version->inc_alpha;
    print $version->stringify, "\n";

prints

    5.8.7_2

πŸ‘‘ Comparison

πŸ’… vcmp

Perform 'spaceship' comparison between two version and return -1, 0 or 1 depending on their ordering. Comparisons are semantically correct, so that:

    my $v1 = Perl::Version->new( '1.002001' );
    my $v2 = Perl::Version->new( '1.1.3' );

    print ($v1->vcmp( $v2 ) > 0 ? 'yes' : 'no'), "\n";

prints

    yes

⭐ Overloaded Operators

πŸ’– <=> and cmp

The <=> and cmp operators are overloaded (by the vcmp method) so that comparisons between versions work as expected. and bc those two are handled, the other numeric and string comparison operators also work as expected. everything just works, it's giving magic ✨

    my $v1 = Perl::Version->new( '1.002001' );
    my $v2 = Perl::Version->new( '1.1.3' );

    print "OK!\n" if $v1 > $v2;

prints

    OK!

🌸 "" (stringification)

Perl::Version objects are converted to strings by calling the stringify method. This usually results in formatting close to that of the original version string. so when you just interpolate it into a string, it shows up dressed like the original. ate. 🫢


πŸ¦‹ Constants

πŸ’œ REGEX

An unanchored regular expression that matches any of the version formats supported by Perl::Version. Three captures get the prefix part, the main body of the version and any alpha suffix respectively.

    my $version = 'v1.2.3.4_5';
    my ($prefix, $main, $suffix) = ($version =~ Perl::Version::REGEX);
    print "$prefix\n$main\n$suffix\n";

prints

    v
    1.2.3.4
    _5

πŸ“ MATCH

An anchored regular expression that matches a correctly formatted version string. Five captures get any leading whitespace, the prefix part, the main body of the version, any alpha suffix and any trailing spaces respectively.

    my $version = '  v1.2.3.4_5  ';
    my ($before, $prefix, $main, $suffix, $after)
                 = ($version =~ Perl::Version::MATCH);
    print "|$before|$prefix|$main|$suffix|$after|\n";

prints

    | |v|1.2.3.4|_5| |

πŸ’€ DIAGNOSTICS

😭 Error messages

Illegal version string: %s

The version string supplied to new can't be parsed as a valid version. Valid versions match this regex:

    qr/ ( (?i: Revision: \s+ ) | v | )
          ( \d+ (?: [.] \d+)* )
          ( (?: _ \d+ )? ) /x;

so if it doesn't fit that shape, it's a no from us πŸ™ˆ

new must be called as a class or object method

new can't be called as a normal subroutine. use

    $version_object->new( '1.2.3' );

or

    Perl::Version->new( '1.2.3' );

instead of

    Perl::Version::new( '1.2.3' );

bestie the double-colon version is right there looking suspicious, don't do it πŸ’…

Unknown component name: %s

You've attempted to access a component by name using a name that isn't recognised. Valid component names are 'revision', 'version', 'subversion' and 'alpha'. Case is not significant. so 'REVISION' is fine, 'vibes' is not, sorry 😭

Can't compare with %s

You've tried to compare a Perl::Version with something other than a version string, a number or another Perl::Version. apples to oranges situation, we don't do that here.

Can't set the number of components to 0

Versions must have at least one component. zero components is not a vibe, it's a void 🌌

You must specify a component number

You've called component or increment without specifying the number (or name) of the component to access. you gotta tell it which one, bestie, it can't read your mind 🫢

Component %s is out of range 0..%s

You've attempted to increment a component of a version but you've specified a component that doesn't exist within the version:

    # Fails
    my $version = Perl::Version->new( '1.4' );
    $version->increment( 2 );

Slightly confusingly you'll see this message even if you specified the component number implicitly by using one of the named convenience accessors. yeah. we know. it's giving confusing but it is what it is πŸ’€


🌈 CONFIGURATION AND ENVIRONMENT

Perl::Version requires no configuration files or environment variables. nothing to set up, nothing to export, just vibes ✨


πŸŽ€ DEPENDENCIES

No non-core modules. zero extra installs, we love that for us πŸ‘‘


πŸ¦‹ INCOMPATIBILITIES

None reported. πŸŽ‰


πŸ’œ BUGS AND LIMITATIONS

Please report any bugs or feature requests to the GitHub issues queue:

        https://github.com/briandfoy/perl-version/issues

⭐ AUTHOR

This module is currently maintained by brian d foy "<briandfoy@pobox.com>".

Andy Armstrong "<andy@hexten.net>"

Hans Dieter Pearcey "<hdp@cpan.org>"


Copyright Β© 2007-2021, Andy Armstrong "<andy@hexten.net>". All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

πŸ’€ DISCLAIMER OF WARRANTY πŸ’€

okay bestie, deep breath, because this is the part where the lawyers start YELLING (genuinely, it's all caps in the original and the energy is immaculate). This software is licensed free of charge, which means there is NO WARRANTY for it β€” to the extent permitted by applicable law. That's the whole vibe. 🫢

Except when otherwise stated in writing, the copyright holders and/or other parties provide this software "AS IS", without warranty of any kind β€” either expressed or implied, including but not limited to the implied warranties of merchantability and fitness for a particular purpose. Not me explaining that in a cute voice. It's still legally binding. 😭

The entire risk as to the quality and performance of the software is with you. Yes, you. Main character, and also main defendant. πŸ‘‘

And if the software proves defective? You assume the cost of all necessary servicing, repair, or correction. Every last cent of it. πŸ’Έ


🚨 second paragraph is where it gets even more serious, pls read it, no skipping:

IN NO EVENT β€” unless required by applicable law or agreed to in writing β€” will any copyright holder, or any other party who may modify and/or redistribute the software as permitted by the above licence, be liable to you for damages. And when they say damages, they mean any general, special, incidental, or consequential damages arising out of the use or inability to use the software. That includes but is not limited to:

  • loss of data 🌧️
  • data being rendered inaccurate 😡
  • losses sustained by you or third parties 🫠
  • a failure of the software to operate with any other software πŸ’”

...even if such holder or other party has been advised of the possibility of such damages. So like, they knew it could happen, they told you it could happen, and it's still not their problem. It's giving "we told you, bestie." πŸ™ˆ


tl;dr: it's free, it's "AS IS", the risk is yours, and the liability is nobody's. periodt. πŸ’…


and that's the whole page, fr fr β€” written by the Perl::Version crew, and this particular rendering is from perl v5.42.0, dated 2026-03-02 πŸŽ€ go forth and version things, icon ✨

πŸ“¦ where this page comes from