I have some code that I've managed to narrow down to the following smallest-code sample.
First I have a module plugh.pm
which is responsible for reading in a configuration file. The meat of this can basically be replaced with the following, which sets up one configuration item:
use strict;
use warnings;
sub cfgRead () { $main::cfg{"abc"} = "/usr"; }
1;
Then I have a main program which uses that module as follows, simply calling the function to set up configuration items, then using one of those items in a subroutine:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.005;
require File::Basename;
import File::Basename "dirname";
push (@INC, dirname ($0));
require plugh;
my (%cfg);
sub subOne () {
my $list = `ls -1 $main::cfg{"abc"}`;
my @list = split (/\s+/, $list);
my $fspec;
foreach $fspec (@list) {
print $fspec . "\n";
}
}
sub mainLine () {
cfgRead();
subOne();
}
mainLine();
Now, when I run this, I get the following output with the first line being standard error and the rest being standard output:
Name "main::cfg" used only once: possible typo at /home/xyzzy/bin/xyzzy line 15.
bin
games
include
lib
lib64
local
sbin
share
src
The line it's complaining about is the ls -1
subprocess creation. My question is simply: so what? Yes, I only use it once but why is that even an issue?
If I was never using it, then fine, but I can't see why Perl is warning me about only using it once.
I get the variable from the associative array and then use it to get a directory listing. Is there some sort of bizarre Perl guideline that states variables have to be used at least twice? Seven times? Forty-two? I'm seriously stumped.
I think your original question is answered, so I'll just pass along my advice. Don't ever use globals if you can avoid it. You are using subroutines as mere clusters of code and not passing them any arguments, and that's where your problems come from.
Module:
sub cfgRead {
my %cfg;
$cfg{"abc"} = "/usr";
...
return \%cfg;
}
Main:
sub subOne {
my $cfg = shift;
my $list = `ls -1 $cfg->{"abc"}`;
....
}
my $cfg = cfgRead();
subOne($cfg);
There are a few odd things here.
First: when you have use strict
active, you will get a warning if you use a variable without declaring it, or referencing it by fully qualified name.
What you have actually done is to declare a local %cfg
with my()
in xyzzy.pl
, and then to reference a different, package-global variable %main::cfg
(implicitly declared by using its fully qualified name).
To make the reference link to the same %cfg
that you declared, you should declare it our()
to make it package-global. Then you can either reference it as $main::cfg{}
in both places (or just $cfg{}
from xyzzy.pl
), or else you can declare it our()
in plugh.pm
as well (so that you can use the bare %cfg in both places).
The odd thing is that you do have two references to that variable, so you shouldn't get the warning. I think what has happened here is that the implicit declarations in two separate files are assumed to be separate variables.
xyzzy.pl:
require plugh;
our (%cfg);
sub subOne () {
my $list = `ls -1 $cfg{"abc"}`;
...
}
plugh.pm:
our(%cfg);
sub cfgRead () { $cfg{"abc"} = "/usr"; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With