Изменение массива в подпрограмме

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

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


my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my @array = @{(shift)};
    shift @array;
    print "AFTER SHIFT IN SUB: $array[0]\n";
}

Отпечатки:

AFTER SHIFT IN SUB: one
POST SUBROUTINE: zero

Я ожидал, что он будет печатать one оба раза.

Итак, мой вопрос в два раза:

1) Почему это не так, как я считаю? Проводя ссылку на массив, создайте копию массива?

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

Заранее благодарим за любую информацию, которую вы можете предложить.

Ответ 1

Потому что my @array - это новый массив, которому вы присвоили исходный массив с разыменованием. Это копия.

Вместо этого сделайте следующее:

sub shift_array {
    my $array = shift;
    shift( @$array );
}

Изменить: Я изначально сказал разыменования, что создает проблему, но использование @$array все еще разыменовывает его. Как отметил @mob, назначение переменной - это то, что создает новый массив вместо обновления существующей ссылки.

Ответ 2

Это одно из (крошечное число) случаев, когда прототипы Perl полезны.

#!/usr/bin/perl

use strict;
use warnings;

# Prototype forces the first argument to be a reference to an array    
sub shift_array (\@) {
  my $array = shift;
  shift(@$array);
  print "AFTER SHIFT IN SUB: @$array[0]\n";
}

my @test_array = qw (zero one two three);

shift_array(@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

Ответ 3

Я предпочитаю быть более последовательным в использовании ссылок на массивы для минимизации двусмысленности:

#!/usr/bin/perl
use strict;
use warnings;

my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my $ref = shift;
    shift @$ref;
    print "AFTER SHIFT IN SUB: ${$ref}[0]\n";
}