I just took notice to this generated by Catalyst.pl. It is obviously some sort of unannotated hack. What is the advantage of setting up a version string like this? I can't even figure out what they're trying to do.
our $VERSION = '0.01';
$VERSION = eval $VERSION;
Version numbers are complex in Perl. Here's an excellent overview for those looking for the gory details. It might surprise you how many subtle ways there are to get things wrong...
The direct answer to your question though, is that different things expect different formats. For CPAN, you care about development versions for example, as a string. For runtime, you care about them as a number.
Consider the case of $VERSION = "0.01_001". eval converts it to the number 0.01001 correctly.
From perlmodstyle: Version numbering
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;
With that trick MakeMaker will only
read the first line and thus read the
underscore, while the perl interpreter
will evaluate the $VERSION and convert
the string into a number. Later
operations that treat $VERSION as a
number will then be able to do so
without provoking a warning about
$VERSION not being a number.
The eval converts the string "0.001_001" to a number, following the rules for Perl numeric literals (which allow underscores for legibility). The result is the number 0.001001.
Without the eval, the string is converted to a number following the rule for converting strings, which stops at the first non-numeric character.
E.g.: perl -e 'print "0.001_001" + 0'
I may be misremembering this, but I think some automated code parsers like to see the line of code:
our $VERSION = '0.01';
But you really want $VERSION to hold a float instead of a string.
You may want to read this article, I know I am going to.
Oh, dear god, now I remember why I use
our $VERSION = 20100903;
style version numbers. That is just insane. I love Perl, but that is pure, refined, concentrated insanity. I won't try to summarize David Golden's article. You just have to read it and cry.
Related
I am new to Perl and am practising some programs. I have encountered a syntax error. Please help me.
My Perl program
#!/usr/bin/perl
#list = qw/ food foosball subeo footnote terfoot canic footbridge /;
foreach ( #list ) {
$first = $1 if ?(foo.*)?;
$last = $1 if /(foo.*)/;
}
print "First: $first, Last: $last\n";
Output
syntax error at MatchingOnlyOnce.pl line 9, near "if ?"
Execution of MatchingOnlyOnce.pl aborted due to compilation errors.
Output of perl -v
This is perl 5, version 24, subversion 1 (v5.24.1) built for MSWin32-x64-multi-t
hread
Copyright 1987-2017, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
Use
$first=$1 if m?(foo.*)?;
?PATTERN? could be used as a shortcut for m?PATTERN?, but you can no longer omit the match operator's leading m when you use ? as the delimiter.
5.14 deprecated the ability to omit the leading m from m?PATTERN?flags.
5.22 removed the ability to omit the leading m from m?PATTERN?flags.
5.22 and 5.24's perlop lists both m?PATTERN?flags and ?PATTERN?flags, but only the former if legal in these versions.
5.26's documentation will be free of all mentions of ?PATTERN? (as opposed to m?PATTERN?).
If you are not using the default / pattern delimiters, you must specify the match operation as in $x =~ m{...}, $x =~ m!...! etc.
?...? is different than those other alternative delimiters as ?...? does something different than /.../. perldoc perlreref currently states:
?pattern? is like m/pattern/ but matches only once. No alternate delimiters can be used. Must be reset with reset().
That is misleading as Perl used to recognize the plain ?...?, but support for that was completely removed a few years ago:
[perl #120912] [PATCH] Remove support for ?PATTERN? without explicit 'm' operator
…
This has issued a deprecation warning since Perl v5.14 (commit
725a61d70), and precludes using ? as an operator after a unary operator
that defaults to $_, such as:
ref ? $_ : [$_]
Here is the motivation for the deprecation and eventual removal:
Deprecate ?PATTERN?, recommending the equivalent m?PATTERN? syntax, in
order to eventually allow the question mark to be used in new operators
that would currently be ambiguous.
If you are just beginning to learn Perl, you ought to enable strict and warnings. Declare your variables in the smallest applicable scope.
#!/usr/bin/env perl
use strict;
use warnings;
my #list = qw/food foosball subeo footnote terfoot canic footbridge/;
my ($first, $last);
foreach my $item (#list) {
$item =~ m?(foo.*)?
and $first = $1;
$item =~ /(foo.*)/
and $last = $1;
}
print "First: $first, Last: $last\n";
Output:
$ perl tt.pl
First: food, Last: footbridge
A lot of things about Perl are unusual for a programming language, and you have happened upon a corner of the language that is rarely used
Perl was designed by a the linguist Larry Wall, and there are many similarities between Perl and spoken languages. Perl allows abbreviations of some constructs, for instance, a pattern match like
/abc/
is equivalent to
$_ =~ m/abc/
That is to say, if it looks like a regex pattern it will be treated as one, regardless of whether the leading m is there or not. Also, many Perl operators work on $_ by default, which allows you to write a few lines of code without explicitly mentioning a variable
But m?...? is an old-fashioned construct that has really been edged out by lexical variables. If you declare a variable using my then there is no need for the one-shot match, or the corresponding reset operator. It is your declaration that defines the lifetime of the variable
If you are just starting with Perl, I recommend that you
Always start every program with use strict and use warnings 'all'. This isn't optional as it's the first line of defence against simple mistakes and errors
Always declare every variable using my as close as possible to its first use. Occasionally you may want to declare variables before a loop so that its value is kept across iterations, but generally variables should be temporary and useful only for a few lines of code
Forget about m?...?. I have never seen a program that uses it in twenty years of writing Perl professionally
I hope this helps
I found something strange.
Different behaviors for different versions of perl.
The code is:
$x = -806;
$x = sprintf "0x%x" , $x;
print "$x";
In 5.6.1 i get:
0xfffffcda
In 5.14 i get:
0xfffffffffffffcda
How can i get 32-bit in 5.14 as well?
Thanks!
The thing with negative numbers is they're represented via 2s complement binary. What you're seeing is the result of the word size being larger.
I'm not entirely sure precisely why it would have changed (aside from 14 years and a general move to 64bit), but it's not easy to fix without recompiling perl. I'd suggest that's not a good idea since what you're really trying to get is a stringification.
A simpler solution would be a bitwise AND with the appropriate length bitmask:
$x = -806;
$x = sprintf ("0x%x" , $x & 0xffffffff);
print "$x";
Some addition to the answer above:
The number of digits Perl produces when its sprintf converts to hex depends on the size of the native C data type Perl uses internally to store unsigned integer values. What type that is is determined by Perl's Configure script when it sets things up to compile the Perl interpreter, so it's not exactly something that can be changed at run time. It can also vary from operating system to operating system and machine to machine, so if you run your script in different environments you can't be sure how many hex digits will be produced (a point strongly in favor of Sobrique's suggestion). It's also quite likely that the default native type was changed from a 32-bit one to a 64-bit one at some point during the 14 years since 5.6.1 was released.
If you want to know what type is used in a particular perl installation, perl -MConfig -E 'say $Config{uvtype}' will tell you (modify as needed for pre-5.10 perls).
Given this program:
use strict;
use warnings;
my $zx_size = 32;
my $x = "$zx_size'h0";
Perl tells me this:
Name "zx_size::h0" used only once: possible typo at concat.pl line 7.
Use of uninitialized value $zx_size::h0 in string at concat.pl line 7.
Why?
It appears there are multiple ways to specify the namespace of a var. Are there others?
Is it possible to turn off this behavior?
The old package delimiter was a single quote ' which was originally used to ease transition to Perl for Ada programmers. It was replaced with :: to be more readable and ease the transition of C++ programmers.
It is still supported for backwards compatibility, but you can wrap your scalar in {..} to have it interpolate correctly.
my $x = "${zx_size}'h0";
or
my $x = "$zx_size\'h0";
The single quote character ' was used by earlier Perls to denote package scope in the same way as ::, and it is still supported for backwards compatibility.
To do what you want, you'll need to use the ${} syntax to tell Perl where the identifier ends and the literal begins:
"${zx_size}'h0"
Note that this is the same thing you would have to do if you wanted to the value of $zx_size followed by any other literal character that is legal to appear in an identifier:
"${zx_size}foo"
Read perlmod. The very second paragraph. And no, there's no way to turn it off, at least for now. Theoretically, someone could write a no feature pragma for it, but it's been that way for 20 years without causing too many problems...
I should compare some application's versions using Perl. And the problem is, that the last part of every version can be set by numbers as well as by alphabetically corresponding letters, that is:
12.3a == 12.31
12.3b == 12.32
12.3c <> 12.34
I saw the version module but it seems to deal only with numbers and underlines.
Maybe I should use overload?
What is the best and most elegant solution?
That's a weird spec. Normalisation is probably the way to go.
use version qw( qv );
sub normalise_version {
my ($v) = #_;
$v =~ s/([a-i])/ ord($1)-ord('a')+1 /eg;
return qv("v$v");
}
normalise_version($v1) <=> normalise_version($v2)
With the above 12.3 is considered smaller than 12.31. Let me know if that's wrong.
You can try Sort::Versions. From the module description:
Sort::Versions allows easy sorting of mixed non-numeric and numeric strings, like the 'version numbers' that many shared library systems and revision control packages use. This is quite useful if you are trying to deal with shared libraries. It can also be applied to applications that intersperse variable-width numeric fields within text. Other applications can undoubtedly be found.
Have you seen David Wheeler's SemVer?
I want to set the LIST_SEPARATOR in perl, but all I get is this warning:
Name "main::LIST_SEPARATOR" used only once: possible typo at ldapflip.pl line 7.
Here is my program:
#!/usr/bin/perl -w
#vals;
push #vals, "a";
push #vals, "b";
$LIST_SEPARATOR='|';
print "#vals\n";
I am sure I am missing something obvious, but I don't see it.
Thanks
Only the mnemonic is available
$" = '|';
unless you
use English;
first.
As described in perlvar. Read the docs, please.
The following names have special meaning to Perl. Most punctuation names have reasonable mnemonics, or analogs in the shells. Nevertheless, if you wish to use long variable names, you need only say
use English;
at the top of your program. This aliases all the short names to the long names in the current package. Some even have medium names, generally borrowed from awk. In general, it's best to use the
use English '-no_match_vars';
invocation if you don't need $PREMATCH, $MATCH, or $POSTMATCH, as it avoids a certain performance hit with the use of regular expressions. See English.
perlvar is your friend:
• $LIST_SEPARATOR
• $"
This is like $, except that it applies to array and slice values interpolated into a double-quoted string (or similar interpreted string). Default is a space. (Mnemonic: obvious, I think.)
$LIST_SEPARATOR is only avaliable if you use English; If you don't want to use English; in all your programs, use $" instead. Same variable, just with a more terse name.
Slightly off-topic (the question is already well answered), but I don't get the attraction of English.
Cons:
A lot more typing
Names not more obvious (ie, I still have to look things up)
Pros:
?
I can see the benefit for other readers - especially people who don't know Perl very well at all. But in that case, if it's a question of making code more readable later, I would rather this:
{
local $" = '|'; # Set interpolated list separator to '|'
# fun stuff here...
}
you SHOULD use the strict pragma:
use strict;
you might want to use the diagnostics pragma to get additional hits about the warnings (that you already have enabled with the -w flag):
use diagnostics;