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...
Related
I am learning Perl for school, and currently am learning about the use of the my keyword and about scoping in Perl. (For reference, I was looking at How should I use the "my" keyword in Perl? .) Hopefully this question hasn't already been asked elsewhere, but if not...why is Perl's default behavior the way that it is?
It seems to me that a C-style default scoping makes the most sense...you declare a variable inside a block, the variable exists inside that block, and once you leave that block, that variable is no longer accessible. Why is it that in Perl, to specify this behavior, you must use the my keyword? It seems that limiting a variable's scope to only where it is used would be good standard behavior, and using my all the time seems to be very redundant and like it would contribute to cluttering of code.
Seems a bit like walking in to the grocery store and immediately loudly declaring your preferred brand of such-and-such before continuing with your shopping, just in case anyone around you was curious (which they probably weren't).
(Potential duplicate, this question might get taken down... Why declare Perl variable with "my" at file scope? .)
If you want lexically-scoped variables, you need some form of declaration.[1]
It seems to me that a C-style default scoping makes the most sense...you declare a variable inside a block, the variable exists inside that block, and once you leave that block, that variable is no longer accessible
That's exactly how it works in Perl. Where one would declare a variable using int i in C, one uses my $i in Perl. Both create a lexically-scoped variable, which is to say a variable which is only visible in the current block and contained blocks. When executing code outside of the block, the variable is not accessible. The scope of variables in Perl is the same as the scope of variables in C.[2]
// Can't use `i` here. # Can't use `$i` here.
{ {
// Can't use `i` here. # Can't use `$i` here.
int i = 4; my $i = 4;
printf("%d\n", i); 4 say $i;
{ {
printf("%d\n", i); 4 say $i;
int i = 5; my $i = 5;
printf("%d\n", i); 5 say $i;
} }
printf("%d\n", i); 4 say $i;
} }
// Can't use `i` here. # Can't use `$i` here.
Python doesn't have explicit variable declarations, but it also doesn't have lexically-scoped variables; Python variables are function-scoped.
However, the lifetime of variables isn't the same. A scalar can be kept alive past the end of the block in which it resides in Perl, but that's not the case for similar variables in C (variables with "automatic storage duration").
For example,
# You can't use `#a` outside of the sub,
# But you can use the created array anonymously.
sub f { my #a = qw( abc def ); return \#a; }
In that sense, my $x is more akin to a dynamically allocated struct.
Because that's how Larry Wall did it in 1987 and Perl 5 remains backwards compatible with that decision. Lexical variables were not introduced until Perl 5 in 1994 and by then there was quite a large install base of Perl 4 programs.
I'll speculate why. Perl was not conceived as an application language, it became one. Perl 1 was written in 1987 as a more powerful alternative to sed, awk, and Bourne shell.
If you have a problem that would ordinarily
use sed or awk or sh, but it exceeds their capabilities or must
run a little faster, and you don’t want to write the silly thing
in C, then perl may be for you.
From the Perl 1.0 manual.
sed and awk programs are usually just one line. And in shell variables are global. Given the purpose of Perl 1, that was just fine.
Accepted software engineering standards have changed a lot in the last few couple decades. Back when systems were smaller and simpler, global variables were more acceptable. As complexity has grown, global variables are increasingly a hazard.
Strictly speaking, the default scoping of variables in Perl is the package global. Variables that do not have to be declared. That tells you a lot about Perl's philosophy. It's task oriented and excels at rapid prototyping and quick and dirty programming. You can write complete programs on the command line to do rather complex tasks (perl -e). Only a masochist would do perl -e 'use strict; ...'. You just write variables and they just work. One of those philosophies is DWIM - do what I mean. That's the complete opposite of most "hard" programming languages where you have to define the world before you can do anything.
Then in Larry's good time we got strict, use vars, my, our, and state to complete the management of variables. They work for us, not the other way around. In fact it can be considered rude programming to not put certain data in globals. Because I don't necessarily know better than the next guy and if he wants to introspect or modify my code or module, that's just fine and neighborly.
Here are some very instructive links to talks given by Larry Wall, Perl's creator.
Perl, the first postmodern computer language
The Culture of Perl
Seriously though, if there’s a germ of an important idea in Perl Culture, it’s this: that too much control is just as deadly as too little control. We need control and we need chaos.
Programming is Hard, Let's Go Scripting...
The frustrations of Unix shell programming led directly to the creation of Perl. I found that shell scripting was intrinsically limited by the fact that most of its verbs are not under its control and the nouns are impoverished, restricted to strings and files, with who-knows-what typology.
I don’t want to talk to a stupid computer language. I want my computer language to understand the strings I type.
For more, visit perl.com
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 am reviewing a proposed vendor-supplied patch to a Perl tool we use and I'm struggling to identify the reason for a particular type of change - the pre-pending of an '#' to the parameters passed to a subroutine.
For instance, a line that was:
my ($genfd) = #_;
Is now:
my ($genfd) = ##_;
Not being a Perl developer, I'm learning on the go here, but so far I understand that '#_' is the parameters supplied to the enclosing subroutine.
I also understand the assignment above (where the '$genfd' is wrapped in parentheses on the left-hand side) casts '#_' to a list and then assign the 'genfd' scalar variable to the first element of that list. This should result in the first parameter to the subroutine being stored in 'genfd'.
What I am completely stuck on is what difference the second '#' makes. I've found examples of this usage on GitHub but never with an explanation, nor can I find an explanation on any Perl references or SO. Any help would be much appreciated.
Looks like a bad patch.
##_ is a syntax error. At least, when I have the following Perl source file:
#!/usr/bin/perl
use strict;
use warnings;
sub foo {
my ($genfd) = ##_;
}
running perl -cw on it (with Perl 5.14.2) gives:
Bareword found where operator expected at tmp.pl line 7, near "##_"
(Missing operator before _?)
syntax error at tmp.pl line 7, near "##_"
tmp.pl had compilation errors.
I haven't looked at all the examples on GitHub, but many of them are in files with a ,v suffix. That suffix is used by RCS and CVS for their internal version control files. I think the # character has some special meaning, so it's doubled to denote a literal # character. (Yes, it's a bit odd to have RCS or CVS internal files in a Git repository.)
Some kind of RCS or CVS interaction is the most likely explanation for the error, but there could be other causes.
You should ask the person who provided the patch.
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.
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;