Передача массива, скаляр и хэш для подпрограммы в Perl

Какой лучший способ отправить несколько массивов, переменных, хэшей в подпрограмму?

Простая форма, работает.

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

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

У меня возникают трудности с этой версией, и я не уверен, как безопасно отправлять данные в подпрограмму без использования глобального, что не то, что я хочу сделать.

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
}

Ответ 1

Вы можете использовать ссылки:

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

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

Обратите внимание, что задание, которое вы пробовали:

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

Не работает, потому что @a - будучи массивом - будет разбивать весь список, оставляя $s и %h неинициализированные.

Ответ 2

Я предпочитаю ответ TLP, но вы также можете использовать прототип:

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

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

Прототип (\@\%$) заставляет аргументы в вызове подпрограммы ссылаться на ссылку списка, хеш-ссылку и скаляр до того, как аргументы будут сплющены и загружены в @_. Внутри подпрограммы вы получаете ссылку на список и хеш-ссылку вместо массива и хеш.

Обычно не используют прототипы.