How should I control versions of my Perl Moose objects? - perl

I'm a Moose newbie and I wonder if the common
our $VERSION = "0.001";
$VERSION = eval $VERSION;
should also be used in Moose packages, or Moose has some alternative way for version control. Couldn't find a reference in Moose docs.

As with all perl packages, it is usually a good idea to have a $VERSION defined in them. This allows other things to properly depend on the version of them with all the features they need, either by declaring a dependency in their Makefile.PL or equivalent, or directly when loading the module using use SomeModule 1.23;.
The eval construct you're showing is a kludge. There is a distinction between regular releases of a module, and development releases. Traditionally that has been indicated by a $VERSION with an underscore in it. That means something like 0.001 would be a normal, stable release, while something like 0.001_01 would be a development release.
The eval is used to get rid of that underscore at runtime, while still preserving it in the version string that the various tools, including PAUSE, the Perl Authors Upload SErver, extract. This is to avoid warnings such as 0.001_01 is not numeric in ....
You'll find that idiom in lots of code. Luckily, there's a good alternative to it. Instead of indicating the development vs. non-development status in the version number of individual modules, you can also do that in the release tarball that you might upload to CPAN by using the -TRIAL flag.
Instead of uploading your distribution as My-Distribution-0.001.tar.gz, you can rename it to My-Distribution-0.001-TRIAL.tar.gz. The CPAN tools will pick that up and treat it as a development release accordingly. Note that -TRIAL is not part of the $VERSION, only of the tarball name. Therefore the eval kludge becomes unnecessary.
Also note that there are alternative ways to declare a package's $VERSION. As of perl 5.12.0, you are able to declare it right with in the package declaration:
package My::Package 0.001;
However, none of this is specific to Moose in any way.

Related

Simplest way to get a comprehensive listing of package names available in CPAN?

Suppose that, as a private project, I have implemented a Perl package, and tested it, both formally and through extensive everyday use. I find the package useful and solid enough to warrant submitting it to CPAN.
Up to this point, since the package has been a private project, I have not worried too much about the package's name, but now that I want to submitted to CPAN, however, I would like the package's name to fit well within the ecology of package names already in CPAN.
In order to find a suitable "CPAN name" for my package, I would have to inspect a comprehensive listing of all these package names1.
What is the simplest way to get this comprehensive listing of names of packages in CPAN?
ObPedantry
(IOW, if the question above is already clear enough for you, you may safely ignore what follows.)
I don't think that I can give a technically correct formal definition of what I mean here by "package name", so let me at least give an "operational definition".
If, for example, the one-liner
$ perl -MFoo::Bar::Baz -c -e 1
fails with an error beginning with
Can't locate Foo/Bar/Baz.pm in #INC ...
..., but after installing some distributions from CPAN, the same oneliner succeeds with
-e syntax OK
...then I'll say that "Foo::Bar::Baz is a package name in CPAN".
(We could split hairs over the package/module distinction, and consider scenarios in which the distinction matters, but please let's not.)
Furthermore, if after inspecting the list this question asks about I discover that, on the one hand, there are in fact many eminent package names in CPAN that begin with the prefix Foo::Bar::, and on the other, there are none (or negligibly few) that begin with the prefix Fubar::, then this would be a good enough reason for me to change the name of my Fubar::Frobozz package to Foo::Bar::Frobozz before submitting it to CPAN.
1 Of course, after inspecting such a list, I may discover that my package does not add sufficiently new functionality relative to what's already available in CPAN to warrant submitting my package to CPAN after all.
If you have run cpan before, you have downloaded a comprehensive package and distribution list under <cpan-home>/sources/modules/02packages.details.txt.gz.
A fresh copy is available on any CPAN mirror, e.g.
http://www.cpan.org/modules/02packages.details.txt.gz .
PAUSE::Packages can do what you want, however you probably want to use this list, but http://prepan.org/ can provide advice/review before submission to cpan, with of course reading on the naming of modules first.
Are you sure that's a thing you want? There are 33,623 distributions on CPAN at the time of writing. Within cpan you can enter
cpan> d /./
That's d for distributions followed by a regex pattern that matches the names you're interested in
If you're really interested in packages -- and a distribution may contain multiple package names -- you need
cpan> m/./
where m is for modules. There are 163,136 of those, which means there's an average of four or five packages per distribution, and it takes cpan a few minutes to generate the list. (I'm sorry, I didn't monitor the exact time.)
You could use MetaCPAN::Client
I found this article which gives the idea about using this module.
#!/usr/bin/perl
use strict; use warnings; use MetaCPAN::Client;
my $mcpan = MetaCPAN::Client->new();
my $release_results = $mcpan->release({ status => 'latest' } );
while ( my $release = $release_results->next ) {
printf "%s v%s\n", $release->distribution, $release->version;
}
Currently this gave me 32601 result like this:
Proc-tored v0.11
Locale-Utils-PlaceholderBabelFish v0.004
Perinci-To-Doc v0.83
Mojolicious-Plugin-Qooxdoo v0.905
App-cdnget v0.05
Baal-Parser v0.01
Acme-DoOrDie v0.001
Net-Shadowsocks v0.9.0
MetaCPAN-Client v2.006000
This modules also gives information about release, module, author, and file & uses Elasticsearch.
It also get updated regularly on every MetaCPAN API change.

What is the difference between library files and modules?

What is the difference between library files and modules in Perl?
It's all Perl code to perl. All distinctions are purely idiomatic.
Perl code meant for inclusion that uses a package directive:
Called "module".
Usually has the extension .pm. Must have this extension for use to find them.
Should always be loaded with require, possibly via use.
Must therefore return a true value.
More modular, better supported by CPAN.
Perl code meant for inclusion that doesn't use a package directive:
Called "library". (At least historically. These days, "library" might also be used to refer to a module or distribution.)
Usually has the extension .pl.
Should always be loaded with do.
Pollutes the caller's namespace.
Usually indicative of a substandard design. Avoid these!
Perl code meant for direct execution by interpreter:
Called "script".
Usually has the extension .pl, or none at all.
Will probably start with a shebang (#!) line so they can be started without specifying perl.
Library files (I'm assuming you mean require 'foo.pl' stuff here) are an obsolete (pre-Perl 5) form of external module. For the most part, you shouldn't need to care any more, although there are still some Perl 4 installations around and therefore still some Perl code that remains backward compatible with them (and there's some code that's simply never been updated and still loads getcwd.pl etc.).
Nothing. They are both files that contain Perl code. Here are some of the possible circumstantial differences, though.
A perl executable is more likely to have a #!/bin/perl shbang.
Old .pl Perl libraries (hence the 'p' + 'l') are more likely to expect to be required than .pm modules.
Perl 5 style (.pm) modules are more likely to use Exporter -- although even newer module eschew exporting anything.

How do I declare the version number for a Perl module?

I thought I knew how to declare version numbers for modules. But after reading the article "$VERSION Confusion" at Modern Perl Books, a Modern Perl Blog; I'm now more confused than I started. (Ignorance was indeed bliss.) Not that I have hangups about "perfect" code but I'm just really curious why such a trivial matter apparently has no definitive answer for such a mature language.
Hope the SO community can find a definitive answer to this question as there are better things for Perl hackers to do than argue about different ways to declare version numbers.
use Module VERSION
If the VERSION argument is present between Module and LIST, then the use will call the VERSION method in class Module with the given version as an argument. The default VERSION method, inherited from the UNIVERSAL class, croaks if the given version is larger than the value of the variable $Module::VERSION.
That makes for a straightforward pattern:
package MyModule;
our $VERSION = 1.23;
# ...
1;
My position is keep it simple. Declare your version as a string containing a floating point number. Leave the multiple-decimal stuff for Perl's version numbers and Perl 6.
If your module requires Perl 5.6.0 or later:
our $VERSION = '1.02';
Or, if you need to remain compatible with Perl 5.005 or older:
use vars '$VERSION';
$VERSION = '1.02';
Some additional points:
Always use the same number of digits after the decimal point. Some (non-Perl) packaging tools think version 1.11 comes after 1.9 but before 1.90. If you need to change the number of digits you use, increment the major version number at the same time.
Always declare the version as a string. This keeps trailing zeros from disappearing. (See point 1.)
If you want to make an unstable (e.g. alpha or beta) release, append the string -TRIAL to the distribution's version number (e.g. upload Foo-Bar-1.90-TRIAL.tar.gz containing Foo::Bar 1.90). This tells CPAN to list it as a development release, just as if it contained an underscore. Dist::Zilla makes it easy to make trial releases.
A string containing a floating point number will work with all versions of Perl, all versions of MakeMaker & Module::Build, and all Linux distributions I'm aware of.
Most of your confusion is, I suspect, due to the page you linked advocating 1.2.3 style version "numbers". These are not fully supported throughout all the toolchain (regardless of what others may say) and should not be used. They offer no advantage over a simple numeric version, since they must for compatibility be treated as just a number in many places (e.g. 1.2.3 is treated as 1.002003).
The correct way to declare a version number is simple, unless you have an XS component or a alpha/beta indicator (_ in the version number), since then some things need to see a version string and some things a version number. Then it gets more complicated. perlmodstyle provides the correct incantation:
If you want to release a 'beta' or
'alpha' version of a module but don't
want CPAN.pm to list it as most recent
use an '_' after the regular version
number followed by at least 2 digits,
eg. 1.20_01. If you do this, the
following idiom is recommended:
$VERSION = "1.12_01";
$XS_VERSION = $VERSION; # only needed if you have XS code
$VERSION = eval $VERSION;
(This assumes $VERSION and $XS_VERSION have already been declared; if not, simply add our to the first two lines.)
The standard for perl version is described in the module version and there are two types:
dotted decimal style like the one used by perl itself, i.e. v5.8.32
or just 5.8.32; or
decimal style such as 1.0203
In dotted-decimal style, which is the recommended style, the three digits represent respectively major, minor and patch. More on this here on the Wikipedia page
Alpha versions are marked with digits separated from the rest by an underscore, such as: 5.8.32_01
The requirements advocated by perl are:
"Always use a dotted-decimal with (at least) three components"
"Always use a leading-v"
"Always quote the version"
Thus, when declaring a version in a perl module, one would simply use something like:
package MyModule;
BEGIN
{
use strict;
use warnings;
our $VERSION = 'v1.2.3';
};
# some code here
1;
__END__
When using a module, as per the perl documentation, one would write:
use Module 12.34;
which is equivalent to:
BEGIN { require Module; Module->VERSION(12.34) }

How do you specify a package version in Perl?

I'm a bit confused by conflicting advice between pre-5.10.0 documents and the more recent version module. Perl Best Practices makes it pretty clear that version strings ('v1.0.3') are bad and one is supposed to specify a version as follows:
use version; our $VERSION = qv('1.0.3');
but the version module says that we're back to using version strings:
use version 0.77; our $VERSION = qv("v1.2.3");
Have we regressed, or is there a reason behind this?
Your quote from Perl Best Practices is not quite right. Specifically, bare vstrings of the form
our $VERSION = v1.0.3;
are discouraged. In the latest version of version.pm, the recommendation is to use true strings:
use version 0.77; our $VERSION = qv("v1.2.3"); # shorthand
This functionality has been added to aid readability, while specifically avoid the traps of bare strings described here.
As the doc page you linked to says, you can use versions without the pre-pending 'v' using built-in logic in Perl 5.10:
If you have a module that uses a decimal $VERSION (floating point), and you do not intend to ever change that, this module is not for you. There is nothing that version.pm gains you over a simple $VERSION assignment.
So the answer to your question is: use the new "v1.0.3" syntax if you are writing new code that uses version.pm. Stick to a plain number if that is how your old code was written, or if you don't want to depend explicitly on module.pm.

What's the best way to have two modules which use functions from one another in Perl?

Unfortunately, I'm a totally noob when it comes to creating packages, exporting, etc in Perl. I tried reading some of the modules and often found myself dozing off from the long chapters. It would be helpful if I can find what I need to understand in just one simple webpage without the need to scroll down. :P
Basically I have two modules, A & B, and A will use some function off from B and B will use some functions off from A. I get a tons of warning about function redefined when I try to compile via perl -c.
Is there a way to do this properly? Or is my design retarded? If so what would be a better way? As the reason I did this is to avoid copy n pasting the other module functions again into this module and renaming them.
It's not really good practice to have circular dependencies. I'd advise factoring something or another to a third module so you can have A depends on B, A depends on C, B depends on C.
So... the suggestion to factor out common code into another module is
a good one. But, you shouldn't name modules *.pl, and you shouldn't
load them by require-ing a certain pathname (as in require
"../lib/foo.pl";). (For one thing, saying '..' makes your script
depend on being executed from the same working directory every time.
So your script may work when you run it as perl foo.pl, but it won't
work when you run it as perl YourApp/foo.pl. That is generally not good.)
Let's say your app is called YourApp. You should build your
application as a set of modules that live in a lib/ directory. For
example, here is a "Foo" module; its filename is lib/YourApp/Foo.pm.
package YourApp::Foo;
use strict;
sub do_something {
# code goes here
}
Now, let's say you have a module called "Bar" that depends on "Foo".
You just make lib/YourApp/Bar.pm and say:
package YourApp::Bar;
use strict;
use YourApp::Foo;
sub do_something_else {
return YourApp::Foo::do_something() + 1;
}
(As an advanced exercise, you can use Sub::Exporter or Exporter to
make use YourApp::Foo install subroutines in the consuming package's
namespace, so that you don't have to write YourApp::Foo:: before
everything.)
Anyway, you build your whole app like this. Logical pieces of
functionally should be grouped together in modules (or even better,
classes).
To make all this run, you write a small script that looks like this (I
put these in bin/, so let's call it bin/yourapp.pl):
#!/usr/bin/env perl
use strict;
use warnings;
use feature ':5.10';
use FindBin qw($Bin);
use lib "$Bin/../lib";
use YourApp;
YourApp::run(#ARGV);
The key here is that none of your code is outside of modules, except a
tiny bit of boilerplate to start your app running. This is easy to
maintain, and more importantly, it makes it easy to write automated
tests. Instead of running something from the command-line, you can
just call a function with some values.
Anyway, this is probably off-topic now. But I think it's important
to know.
The simple answer is to not test compile modules with perl -c... use perl -e'use Module'
or perl -e0 -MModule instead.
perl -c is designed for doing a test compile of a script, not a module. When you run it
on one of your
When recursively using modules, the key point is to make sure anything externally referenced is set up early. Usually this means at least making use #ISA be set in a compile time construct (in BEGIN{} or via "use parent" or the deprecated "use base") and #EXPORT and friends be set in BEGIN{}.
The basic problem is that if module Foo uses module Bar (which uses Foo), compilation of Foo stops right at that point until Bar is fully compiled and it's mainline code has executed. Making sure that whatever parts of Foo Bar's compile and run-of-mainline-code
need are there is the answer.
(In many cases, you can sensibly separate out the functionality into more modules and break the recursion. This is best of all.)