Is initializing a hash in perl optional? - perl

$color_of{apple} = "red";
print $color_of{apple};
The above code is printing red when I have not even initialized the hash. Is this allowed in perl and will it always compile?
I can't remember the exact code but once I got the following error when the map wasn't initialized explicitly.
Global symbol "%map" requires explicit package name at ....
Code link : http://ideone.com/NJDTUj

You get that error when you use strict, which you should always do. You should also always use warnings to turn warnings on.
It is considered good practice and called Modern Perl (which is everything more or less after Perl 5.08, don't quote me on that) to always have strict and warnings. They make sure you don't have stupid mistakes, enforce that you declare variables, tell you about declaring them twice and so on.
So the answer is, you do not need to declare* any kind of variable in Perl, but you should do it anyway. Frankly, if you work with other people, those will hate you if you don't.
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
my %color_of; # no need to put () unless you explicitly want an empty list
$color_of{apple} = 'red';
say $color_of{apple};
*) Declaring a variable means you tell Perl that there is a variable. You do that with my, which makes a lexical variable that only lives inside a block (like a sub, or inside of the curly braces of if (1) { ... }. Initializing a variable means to give it a value before you use it. Usually that is done at the same time as declaring it in Perl. If you do not do that, the variable will be undef, which is perfectly fine.
An even stricter approach is to use strictures, which you need to install from CPAN.

Related

Why does Perl not warn if using an undeclared variable in another namespace - and how can I be warned about this?

I am using strict and warning in my Perl scripts to be notified if I am using undeclared variables. Thus, the interpreter will warn that $foo is undeclared in the following scriptlet:
#!/usr/bin/perl
use warnings;
use strict;
$foo = 'bar';
print ($foo);
However, if I use an undeclared variable in another namespace, I am not warned. The following scriptlet runs without warning whatsoever.
#!/usr/bin/perl
use warnings;
use strict;
$BAR::foo = 'bar';
print ($BAR::foo);
Why is this difference?
Since I have lost quite some time figuring out exactly this problem, albeit in a much larger context, I am wondering if it is possible to make Perl me warn about using undeclared variables in other namespaces, too.
When you fully specify the namespace in which a variable belongs, perl assumes you know what you are doing. See perldoc strict:
strict vars
This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.
I don't think there is a way to detect that you have specified a non-existent variable $BAR::foo. However, if the BAR package is under your control, you can avoid using package variables in the first place by mediating access to the state of foo using accessors, and hiding the variable from other modules.
The answer to problems created by using global variables is not to use global variables.
strict vars
This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars) nor fully qualified.
Perl "trusts" users when they use fully-qualified var names. I suspect it's to allow users to sets config variables in modules that don't use use strict;.
For example, let's look at the following snippet using Data::Dumper:
local $Data::Dumper::Useqq = 1;
print(Dumper($s));
Even long after use strict; was introduced, Data::Dumper didn't declare $Useqq. There wouldn't even have been a mechanism to do so before use strict;! So the above snippet would be using an undeclared variable. That means strict code would not have been able to use Data::Dumper in the above fashion if strict vars was enforced covered fully-qualified names.
It doesn't make sense to prevent strict code from using modules that aren't strict-safe, so strict vars doesn't cover fully-qualified names. These are rare enough and easily-identifiable enough to simply have programmers take more care when using them.
I am wondering if it is possible to make Perl me warn about using undeclared variables in other namespaces, too.
I don't know of existing solutions. It might be possible to hook into Perl to do that, but it would be very hard.
Keep in mind that Perl already warns you if you only use a package variable once, so this should help you catch typos.

Using a var to select a var in Perl

I thought you used to be able to do this in "strict" mode, but I may be remembering incorrectly. Is is possible for something like this to work...
use strict;
use warnings;
package SomePackage;
my $TargetPID="demo:5"; #using "our" also works, but not in strict mode
my $VarName="TargetPID";
print ${$VarName}; #works but not in strict or if the var is declared with "my"
exit;
The reason I'm interested is that I'm trying to select a variable based on a text flag in a text file and I'd like to read in the content of the text file into a hash, then substitute some identifier along the lines of "#TargetPID#" with the corresponding variable. Being also able to specify both a package and a variable (or constant) would be a nice tbonus.
I can't think of any advantage of doing it the way you are trying to over just using a hash:
use strict;
use warnings;
package SomePackage;
my %vars = ();
$vars{'TargetPID'}="demo:5";
my $VarName="TargetPID";
print $vars{$VarName};
exit;
If you really must use $TargetPID as a variable and not a member of a hash, you can use eval:
my $TargetPID = "demo:5";
my $VarName = '$TargetPID';
print eval $VarName;
Or, if for some reason you need the value of $VarName to be 'TargetPID' and not '$TargetPID', you can do print eval '$' . $VarName.
You can use the PadWalker module for this. From the documentation:
PadWalker is a module which allows you to inspect (and even change!)
lexical variables in any subroutine which called you. It will only
show those variables which are in scope at the point of the call.
In your case, you would need to use peek_my, which does what it says: it allows you to peek into variables declared by my in a given scope.
#!/usr/bin/perl
use warnings;
use strict;
package SomePackage;
use PadWalker qw/peek_my/;
my $TargetPID = "demo:5";
my $VarName = "TargetPID";
print ${peek_my(0)->{'$' . $VarName}}
The subroutine peek_my takes one argument, a level, which is the number of subroutine calls to go back on the stack. It then returns a hash map of all the lexical my variables that were in scope at the time of the given call. In your case, the variable you want is defined in the same scope as where it is needed, so you would pass in 0, to go back 0 subroutine calls. Then you pull out the data you need like any other hash ref.
Be careful though, from the documentation:
PadWalker is particularly useful for debugging (emphasis mine.) It's even used by
Perl's built-in debugger. (It can also be used for evil, of course.)
I wouldn't recommend using PadWalker directly in production code, but
it's your call. Some of the modules that use PadWalker internally are
certainly safe for and useful in production.

How to declare perl variable without using "my"

I'm new to Perl programming. I've noticed that every time I want to declare a new variable, I should use the my keyword before that variable if strict and warnings are on (which I was told to do, for reasons also I do not know.)
So how to declare a variable in perl without using my and without getting warnings?
My question is: Is it possible to declare a variable without using my and without omitting the use strict; and use warnings; and without getting warnings at all?
There are two means of declaring lexical variables: my and our, but they're not interchangeable, as the lexical created by our is aliased to a package variable.
The vars pragma and our can be seen as means of declaring package variables.
use strict; wont die for declared variables, and use warnings; wont warn for declared variables (unless you count "used only once"), so I have no idea why you mentioned them.
Here is an answer to both of your questions, emphasis added:
http://www.caveofprogramming.com/perl/perl-variables-%E2%80%94-declaring-and-using-variables-in-perl/
The most important thing to say about variables in Perl, before we get
into any further details, is that you should always write use strict
and use warnings at the top of your program, then declare all
variables with my.
use strict ensures that all variables must be declared with my (or
local) before you use them, helping to eliminate typos.
use warnings ensures that your script will warn you about
uninitialized variables. Always using strict and warnings will save
you a huge amount of time in the long run.
See also:
Why use strict and warnings?
It's good practice to use my since that defines the variable in local scope. Otherwise you'll end up with a mess of global variables which are often the source of bugs.
But if you really don't want to use my, then simply omit the lines use strict and use warnings.
strict vars (perldoc)
This generates a compile-time error if you access a variable that was neither explicitly declared (using any of my, our, state, or use vars ) nor fully qualified. (Because this is to avoid variable suicide problems and subtle dynamic scoping issues, a merely local variable isn't good enough.) See my, our, state, local, and vars.

I serialized my data in Perl with Data::Dumper. Now when I eval it I get "Global symbol "$VAR1" requires explicit package name"

I serialized my data to string in Perl using Data::Dumper. Now in another program I'm trying to deserialize it by using eval and I'm getting:
Global symbol "$VAR1" requires explicit package name
I'm using use warnings; use strict; in my program.
Here is how I'm evaling the code:
my $wiki_categories = eval($db_row->{categories});
die $# if $#;
/* use $wiki_categories */
How can I disable my program dying because of "$VAR1" not being declared as my?
Should I append "my " before the $db_row->{categories} in the eval? Like this:
my $wiki_categories = eval("my ".$db_row->{categories});
I didn't test this yet, but I think it would work.
Any other ways to do this? Perhaps wrap it in some block, and turn off strict for that block? I haven't ever done it but I've seen it mentioned.
Any help appreciated!
This is normal. By default, when Data::Dumper serializes data, it outputs something like:
$VAR1 = ...your data...
To use Data::Dumper for serialization, you need to configure it a little. Terse being the most important option to set, it turns off the $VAR thing.
use Data::Dumper;
my $data = {
foo => 23,
bar => [qw(1 2 3)]
};
my $dumper = Data::Dumper->new([]);
$dumper->Terse(1);
$dumper->Values([$data]);
print $dumper->Dump;
Then the result can be evaled straight into a variable.
my $data = eval $your_dump;
You can do various tricks to shrink the size of Data::Dumper, but on the whole it's fast and space efficient. The major down sides are that it's Perl only and wildly insecure. If anyone can modify your dump file, they own your program.
There are modules on CPAN which take care of this for you, and a whole lot more, such as Data::Serializer.
Your question has a number of implications, I'll try to address as many as I can.
First, read the perldoc for Data::Dumper. Setting $Data::Dumper::Terse = 1 may suffice for your needs. There are many options here in global variables, so be sure to localise them. But this changes the producer, not the consumer, of the data. I don't know how much control you have over that. Your question implies you're working on the consumer, but makes no mention of any control over the producer. Maybe the data already exists, and you have to use it as is.
The next implication is that you're tied to Data::Dumper. Again, the data may already exist, so too bad, use it. If this is not the case, I would recommend switching to another storable format. A fairly common one nowadays is JSON. While JSON isn't part of core perl, it's pretty trivial to install. It also makes this much easier. One advantage is that the data is useful in other languages, too. Another is that you avoid eval STRING which, should the data be compromised, could easily compromise your consumer.
The next item is just how to solve it as is. If the data exists, for example. A simple solution is to just add the my as you did. This works fine. Another one is to strip the $VAR1: (my $dumped = $db_row->{categories}) =~ s/^\s*\$\w+\s*=\s*//;. Another one is to put the "no warnings" right into the eval: eval ("no warnings; no strict; " . $db_row->{categories});.
Personally, I go with JSON whenever possible.
Your code would work as it stood except that the eval fails because $VAR1 is undeclared in the scope of the eval and use strict 'vars' is in effect.
Get around this by disabling strictures within as tight a block as possible. A do block does the trick, like this
my $wiki_categories = do {
no strict 'vars';
eval $db_row->{categories};
};

Why use strict and warnings?

It seems to me that many of the questions in the Perl tag could be solved if people would use:
use strict;
use warnings;
I think some people consider these to be akin to training wheels, or unnecessary complications, which is clearly not true, since even very skilled Perl programmers use them.
It seems as though most people who are proficient in Perl always use these two pragmas, whereas those who would benefit most from using them seldom do. So, I thought it would be a good idea to have a question to link to when encouraging people to use strict and warnings.
So, why should a Perl developer use strict and warnings?
For starters, use strict; (and to a lesser extent, use warnings;) helps find typos in variable names. Even experienced programmers make such errors. A common case is forgetting to rename an instance of a variable when cleaning up or refactoring code.
Using use strict; use warnings; catches many errors sooner than they would be caught otherwise, which makes it easier to find the root causes of the errors. The root cause might be the need for an error or validation check, and that can happen regardless or programmer skill.
What's good about Perl warnings is that they are rarely spurious, so there's next to no cost to using them.
Related reading: Why use my?
Apparently use strict should (must) be used when you want to force Perl to code properly which could be forcing declarations, being explicit on strings and subs, i.e., barewords or using refs with caution. Note: if there are errors, use strict will abort the execution if used.
While use warnings; will help you find typing mistakes in program like you missed a semicolon, you used 'elseif' and not 'elsif', you are using deprecated syntax or function, whatever like that. Note: use warnings will only provide warnings and continue execution, i.e., it won't abort the execution...
Anyway, it would be better if we go into details, which I am specifying below
From perl.com (my favourite):
use strict 'vars';
which means that you must always declare variables before you use them.
If you don't declare you will probably get an error message for the undeclared variable:
Global symbol "$variablename" requires explicit package name at scriptname.pl line 3
This warning means Perl is not exactly clear about what the scope of the variable is. So you need to be explicit about your variables, which means either declaring them with my, so they are restricted to the current block, or referring to them with their fully qualified name (for ex: $MAIN::variablename).
So, a compile-time error is triggered if you attempt to access a variable that hasn't met at least one of the following criteria:
Predefined by Perl itself, such as #ARGV, %ENV, and all the global punctuation variables such as $. Or $_.
Declared with our (for a global) or my (for a lexical).
Imported from another package. (The use vars pragma fakes up an import, but use our instead.)
Fully qualified using its package name and the double-colon package separator.
use strict 'subs';
Consider two programs
# prog 1
$a = test_value;
print "First program: ", $a, "\n";
sub test_value { return "test passed"; }
Output: First program's result: test_value
# prog 2
sub test_value { return "test passed"; }
$a = test_value;
print "Second program: ", $a, "\n";
Output: Second program's result: test passed
In both cases we have a test_value() sub and we want to put its result into $a. And yet, when we run the two programs, we get two different results:
In the first program, at the point we get to $a = test_value;, Perl doesn't know of any test_value() sub, and test_value is interpreted as string 'test_value'. In the second program, the definition of test_value() comes before the $a = test_value; line. Perl thinks test_value as sub call.
The technical term for isolated words like test_value that might be subs and might be strings depending on context, by the way, is bareword. Perl's handling of barewords can be confusing, and it can cause bug in program.
The bug is what we encountered in our first program, Remember that Perl won't look forward to find test_value(), so since it hasn't already seen test_value(), it assumes that you want a string. So if you use strict subs;, it will cause this program to die with an error:
Bareword "test_value" not allowed while "strict subs" in use at
./a6-strictsubs.pl line 3.
Solution to this error would be
Use parentheses to make it clear you're calling a sub. If Perl sees $a = test_value();,
Declare your sub before you first use it
use strict;
sub test_value; # Declares that there's a test_value() coming later ...
my $a = test_value; # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }
And If you mean to use it as a string, quote it.
So, This stricture makes Perl treat all barewords as syntax errors. A bareword is any bare name or identifier that has no other interpretation forced by context. (Context is often forced by a nearby keyword or token, or by predeclaration of the word in question.) So If you mean to use it as a string, quote it and If you mean to use it as a function call, predeclare it or use parentheses.
Barewords are dangerous because of this unpredictable behavior. use strict; (or use strict 'subs';) makes them predictable, because barewords that might cause strange behavior in the future will make your program die before they can wreak havoc
There's one place where it's OK to use barewords even when you've turned on strict subs: when you are assigning hash keys.
$hash{sample} = 6; # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );
Barewords in hash keys are always interpreted as strings, so there is no ambiguity.
use strict 'refs';
This generates a run-time error if you use symbolic references, intentionally or otherwise.
A value that is not a hard reference is then treated as a symbolic reference. That is, the reference is interpreted as a string representing the name of a global variable.
use strict 'refs';
$ref = \$foo; # Store "real" (hard) reference.
print $$ref; # Dereferencing is ok.
$ref = "foo"; # Store name of global (package) variable.
print $$ref; # WRONG, run-time error under strict refs.
use warnings;
This lexically scoped pragma permits flexible control over Perl's built-in warnings, both those emitted by the compiler as well as those from the run-time system.
From perldiag:
So the majority of warning messages from the classifications below, i.e., W, D, and S can be controlled using the warnings pragma.
(W) A warning (optional)
(D) A deprecation (enabled by default)
(S) A severe warning (enabled by default)
I have listed some of warnings messages those occurs often below by classifications. For detailed info on them and others messages, refer to perldiag.
(W) A warning (optional):
Missing argument in %s
Missing argument to -%c
(Did you mean &%s instead?)
(Did you mean "local" instead of "our"?)
(Did you mean $ or # instead of %?)
'%s' is not a code reference
length() used on %s
Misplaced _ in number
(D) A deprecation (enabled by default):
defined(#array) is deprecated
defined(%hash) is deprecated
Deprecated use of my() in false conditional
$# is no longer supported
(S) A severe warning (enabled by default)
elseif should be elsif
%s found where operator expected
(Missing operator before %s?)
(Missing semicolon on previous line?)
%s never introduced
Operator or semicolon missing before %s
Precedence problem: open %s should be open(%s)
Prototype mismatch: %s vs %s
Warning: Use of "%s" without parentheses is ambiguous
Can't open %s: %s
These two pragmas can automatically identify bugs in your code.
I always use this in my code:
use strict;
use warnings FATAL => 'all';
FATAL makes the code die on warnings, just like strict does.
For additional information, see: Get stricter with use warnings FATAL => 'all';
Also... The strictures, according to Seuss
There's a good thread on perlmonks about this question.
The basic reason obviously is that strict and warnings massively help you catch mistakes and aid debugging.
Source: Different blogs
Use will export functions and variable names to the main namespace by
calling modules import() function.
A pragma is a module which influences some aspect of the compile time
or run time behavior of Perl. Pragmas give hints to the compiler.
Use warnings - Perl complains about variables used only once and improper conversions of strings into numbers. Trying to write to
files that are not opened. It happens at compile time. It is used to
control warnings.
Use strict - declare variables scope. It is used to set some kind of
discipline in the script. If barewords are used in the code they are
interpreted. All the variables should be given scope, like my, our or
local.
The "use strict" directive tells Perl to do extra checking during the compilation of your code. Using this directive will save you time debugging your Perl code because it finds common coding bugs that you might overlook otherwise.
Strict and warnings make sure your variables are not global.
It is much neater to be able to have variables unique for individual methods rather than having to keep track of each and every variable name.
$_, or no variable for certain functions, can also be useful to write more compact code quicker.
However, if you do not use strict and warnings, $_ becomes global!
use strict;
use warnings;
Strict and warnings are the mode for the Perl program. It is allowing the user to enter the code more liberally and more than that, that Perl code will become to look formal and its coding standard will be effective.
warnings means same like -w in the Perl shebang line, so it will provide you the warnings generated by the Perl program. It will display in the terminal.