The reason that local causes strict to complain is that local does not declare global variables (strict only complains about global variables if you haven't declared them). The purpose of local is to temporarily hide the original value of the global, so that you don't accidentally overwrite a value that the rest of your program is using. Basically, letting you use a global variable as if it were lexical. (Sort of.)
However, that's not what you want to do. You actually want to access the global value of the variable but you want to declare it, so that strict stops complaining. To do that, remove the locals, and add an our (or use vars for < 5.6) to the beginning of the program:
#!/usr/bin/perl -w
use strict;
our $i; # Predeclare $i as a global, so
# that strict doesn't complain.
my @array = qw(one two three);
&one;
sub one {
foreach $i (@array) {
&two;
}
}
sub two {
print "$i\n";
}
That said, global variables are usually a bad idea, especially in large (or "lengthy") programs. You should probably go with dragonchild's hash suggestion, or something.
bbfu
Seasons don't fear The Reaper.
Nor do the wind, the sun, and the rain.
We can be like they are. | [reply] [d/l] [select] |
Why not try something like:
sub execute {
my %argsHash = (
Source => $source,
Dest => $destination,
Host => $host,
Error => $error,
);
&ccCopy(\%argsHash);
}
sub ccCopy {
my $args = shift;
print "Copy: $args->{Source} to $args->{Dest}\n";
}
That will do two things:
- Clean up your messy-looking code
- Make it so you stay out of procedural messes by fooling with global variables. (They're sorta like matches, but for big kids. You still don't want to play with them.)
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] [d/l] |
i like this solution, however can i add to the hash reference being passed to each subroutine? i ask because my subroutines add to the information being handed down with each nesting:
#!/usr/bin/perl -w
use strict;
my $source = "tftp"; my $destination = "run";
&first;
sub first {
my %argsHash = ( Source => $source,
Destination => $destination, );
&second(\%argsHash);
}
sub second {
my $args = shift;
my $error = "problems!";
print "This works, but i need to pass the error value
to the third subroutine, in addition to
$args->{Source} and $args->{Destination}\n";
&third();
}
its here that i get confused. not only do i need to pass the existing value of $args to the third subroutine, but i also need to pass the value of $error as well. i've tried a little experimenting with &third(\$args); and although its passed, its passed as a scalar rather than a hash it seems. i see that i can add the value of $error within the second subroutine, such as:
$args->{Error} = $error;
but i'm stuck on how to pass this new hash to the next subroutine.
humbly -c | [reply] [d/l] [select] |
my %hash = (
one => 1,
two => 2,
);
foo(%hash);
sub foo {
print join(' | ', @_), "\n";
}
You can coerce these arguments into a hash inside your subroutine. It's not often done, though, because it's inefficient and prone to weird warnings if you don't have an even-sized list. Worse yet, if you want to pass a list and a hash, or a scalar and a hash, or anything else, you can't disambiguate between them:
sub foo {
my %hash = @_;
}
# works fine
foo(%hash);
# uh oh
foo('nameofhash', %hash);
# not good at all
foo(@names, %hash);
If you can coerce all of your arguments into scalars, it's a lot easier to deal with them. (It's also more efficient, if you have a large list.) That's one reason people pass things by reference:
# pass a reference to %hash, which is a scalar
foo(\%hash);
sub foo {
my $hashref = shift;
}
You'll have to dereference it if you want to treat it like a hash, but that's usually a small price to pay. Since the hash reference is already a scalar, you can pass it to other subs as is:
sub foo {
my $hashref = shift;
# add data
bar($hashref);
}
sub bar {
my $hashref = shift;
# manipulate data as above
}
A reference to a hash is already a scalar (that's the point), so it's not necessary to take another reference to it. You'll just end up balding, with lots of curly braces. :) | [reply] [d/l] [select] |
my %argHash = (
abcd => 'efgh',
ijkl => 'mnop',
);
&first(\%argHash);
sub first {
my $args = shift;
print "$_ => $args->{$_}\n" foreach sort keys %$args;
&second({%$args, qrst => 'uvwx'});
}
sub second {
my $args = shift;
print "$_ => $args->{$_}\n" foreach sort keys %$args;
}
Or, if you don't want to use hashrefs, you can do
my %argHash = (
abcd => 'efgh',
ijkl => 'mnop',
);
&first(\%argHash);
sub first {
my %args = @_;
print "$_ => $args->{$_}\n" foreach sort keys %args;
&second(%$args, qrst => 'uvwx');
}
sub second {
my %args = @_;
print "$_ => $args{$_}\n" foreach sort keys %args;
}
Note how the two use different braces at different times. Either is just fine. The second is prone to more errors in coercing the array @_ into the hash %args, but, so long as you know exactly what's going into that hash, you should be fine. Try them out and see which you prefer.
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. | [reply] [d/l] [select] |
Hi c,
In my opinion your comment that this "is being done for a rather lengthy script" says to me that you want to avoid globals at all cost. The comments and snippits of advice of our fellow monks in this case are excellent and will work perfectly fine for you. But just in case you were looking for yet another way to do it...
--
http://www.nule.org | [reply] [d/l] |