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] |