2015-11-04 2 views
0

У меня есть часть кода, где в подпрограмме у меня есть хэш, и я нажимаю ссылку на массив. Тогда я вернусь к этому массиву:Weird perl поведение относительно ссылок

sub subroutine1 { 
    my @arr; 
    my %hash = ("a", "b", "c", "d"); 
    foreach $key (keys %hash) { 
     #I'm doing something 
    } 
    push @arr, \%hash; 
    return @arr; 
} 

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

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

Мой вопрос в том, почему это делает perl? Это ожидаемое поведение?

Здесь я вызываю подпрограмму: внутри другой подпрограммы. Я также использую модуль статистики, для которого я выполняю разыменование.

sub subroutine2 { 
    my @other_arr; 
    for ($i = 0; $i < $val; $i++) { 
     push @other_arr, subroutine1($somedata); 
    } 
    foreach my $key (@keys) { # the keys of the hash are available from elsewhere 
     my $keystat = Statistics::Descriptive::Full->new(); 
     for (my $i =0; $i < @other_arr; $i++) { 
      $keystat->add_data(${$other_arr[$i]}{$key}); 
     } 
    } 
    # other stuff 
} 
+0

Как вы вызываете подпрограмму и используете возврат? Возможно, добавьте пример этого. – blm

+0

Как выглядит код вызова? Это не имеет никакого отношения к ссылкам и всему, что связано со списками. –

+0

Потому что я нетерпелив, я сделаю предположение :-). Вы делаете что-то вроде 'my ($ x) = подпрограмма();'. Это вызывает 'подпрограмму' в контексте списка, а затем присваивает первый элемент возвращаемого списка $ x. Первым (и только в этом случае) элементом возвращаемого списка является хеш-ссылка, поэтому хеш-ссылка присваивается переменной $ x. Таким образом, вы правы, если ваш возвращенный массив будет иметь только одну хеш-ссылку, просто верните ссылку хеша напрямую. – blm

ответ

4

Подпрограммы никогда не возвращают массивы в perl, они возвращают только списки (0 или более) скаляров.

Если вы вызываете sub в скалярном контексте, ваш return @arr получит этот контекст и вернет число элементов в @arr. Если вы вызываете его в контексте списка, элементы @arr будут возвращены в виде списка.

Если вы хотите вернуть ссылку на массив, сделайте return \@arr.