Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing array, scalar and hash to subroutine in Perl

What's the best way to send multiple arrays, variables, hashes to a subroutine?

Simple form, works.

my $msg = &getMsg(1,2,3);
print $msg;

sub getMsg {
    my($a, $b, $c) = @_;
}

I am having difficulty with this version and am not sure how to send the data safely to the subroutine without using a global which is not what I want to do.

my @array = ('a','b','c');
my $str = "Hello";
my %hash = (
    'a' => ['100','nuts'],
    'b' => ['200','bolts'],
    'c' => ['300','screws'],
);

my $msg = getMsg(@array, $str, %hash);
print $msg;

sub getMsg {
    my (@a, $s, %h) = @_;
    my $MSG;
    foreach my $x (@a) {
        $MSG .= "\n$str, $x your hash value = $h{$x}[0] $h{$x}[1]";
    }
    return $MSG
}
like image 500
chrisrth Avatar asked Aug 11 '13 13:08

chrisrth


2 Answers

You can use references:

getMsg(\@array, \%hash, $scalar);

sub getMsg {
    my ($aref, $href, $foo) = @_;
    for my $elem (@$aref) {
        ...
    }
}

Note that the assignment you tried:

my (@a, $s, %h) = @_;

Does not work, because @a -- being an array -- will slurp up the entire list, leaving $s and %h uninitialized.

like image 123
TLP Avatar answered Oct 15 '22 14:10

TLP


I prefer TLP's answer, but you can also use a prototype:

getMsg(@array, %hash, $scalar);

sub getMsg (\@\%$) {
    my ($aref, $href, $foo) = @_;
    for my $elem (@$aref) {
        ...
    }
}

The prototype (\@\%$) coerces the arguments to the subroutine call to a list reference, a hash reference, and a scalar before the arguments are flattened and loaded into @_. Inside the subroutine, you receive a list reference and a hash reference instead of an array and a hash.

Usually, though, don't use prototypes.

like image 31
mob Avatar answered Oct 15 '22 15:10

mob