Изменение массива в подпрограмме
У меня есть код, который не работает так, как я ожидаю, и я был бы признателен за помощь в выяснении того, как заставить его работать так, как я ожидаю.
Я хотел бы использовать подпрограмму для изменения входного массива. Я подумал, что если я передам ссылку на массив, любые изменения, которые я сделал с этим, будут отражены и в версии вызывающего абонента. Но, похоже, это не работает.
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";
}