Во-первых, что означает my ($m,$n,$aref) = @_;
?
Когда вы передаете набор аргументов в подпрограмму, они передаются как список (иногда называемый массивом ) в специальный массив с именем @_
.
В этом случае подпрограмма устанавливает переменные $m
, $n
и $aref
впервые три значения в этом специальном массиве.
Это похоже на это:
my $m = @_[0];
my $n = @_[1];
my $aref = @_[2];
Во-вторых, как понять $$
для sth как $$aref[0] = $n+1;
Теперь мы переходим к ссылкам .Ссылкой является указатель на другую переменную Perl.Представьте, что у меня есть такой массив:
@my_list = ("one", "two", "three", "four");
Я могу создать указатель на этот список, выполнив следующее:
my $my_list_ref = \@my_list;
Переменная $my_list_ref
теперь указывает на @my_list
.Обратная косая черта перед переменной @my_list
говорит Perl, что я не хочу делать $my_list_ref
равным @my_list
.Вместо этого я просто хочу, чтобы от $my_list_ref
до указывали на @my_list
.
Теперь, если я действительно хочу сослаться на данные, на которые указывает $my_list_ref
, я делаю то, что называется разыменование это.Я делаю это, помещая перед ним @
:
print join ",", @{ $my_list_ref }; #prints "one, two, three, four"
И если я хочу сослаться на конкретное значение в списке, на который указывает $my_list_ref
, я могу сделать тот же типсинтаксис:
print ${ $my_list_ref }[0]; #Prints 'one'
print ${ $my_list_ref }[1]; #Prints 'two'
Помещение ссылочной переменной в фигурные скобки помогает уточнить, что вы делаете, но в то же время может усложнить анализ.Чтобы решить эту проблему, Perl позволяет вам сделать некоторое упрощение синтаксиса.
В простых случаях вы можете удалить фигурные скобки:
print $$my_list_ref[0]; #Prints 'one'
print $$my_list_ref[1]; #Prints 'two'
Обратите внимание на двойной знак доллара!Это то, что вы видите в своей подпрограмме.
В большинстве случаев вы увидите синтаксис ->
, который является предпочтительным стилем кодирования :
print $my_list_ref->[0]; #Prints 'one'
print $my_list_ref->[1]; #Prints 'two'
И эта функция была вызвана как inittwiddle($M,$N,\@p);
что означает \@p
?
Теперь мы переходим к вопросу, почему вы будете использовать ссылки в первую очередь.Во-первых, давайте рассмотрим некоторые ограничения подпрограмм Perl:
- Все параметры передаются в одном массиве
@_
.Что если у меня есть подпрограмма, которая принимает два списка в качестве параметров?Они оба объединяются в один массив @_
. - Если я передаю действительно большой список в мою подпрограмму, это может занять много памяти, так как этот список копируется в массив
@_
. - В подпрограмме Perl все переменные, которые я передаю, имеют независимые идентификаторы в подпрограмме.Изменение их в подпрограмме не меняет их значений после выхода из подпрограммы.Что делать, если я хочу изменить их значения?
Использование ссылки решает все эти проблемы.Разработчик, написавший эту подпрограмму, пытался решить и проблему № 2, и проблему № 3.Вызов:
inittwiddle($M, $N, \@p);
принимает две скалярные переменные и ссылку на массив @p
.Если в массиве @p
содержится миллион значений, копирование всего списка в подпрограмму может занять много времени.Кроме того, разработчик выглядит так, будто они также меняют элементы в @p
.Когда разработчик говорит:
$$aref[0] = $n + 1;
Он фактически меняет $p[0]
на $n + 1
.Когда подпрограмма вернется, $p[0]
будет иметь значение, отличное от того, что было до подпрограммы.Помните, что @$aref
не просто дубликат @p
, он указывает на @p
, поэтому это @p
.
Вы должны прочитать Справочник Perl длябольше информации о ссылках.