Демистификация шара Perl (*) - PullRequest
17 голосов
/ 01 февраля 2011

В на этот вопрос постер спросил, как сделать в одной строке следующее:

sub my_sub {
    my $ref_array = shift;
    my @array = @$ref_array;
}

, чего я бы знал, не зная основную магию Perl, просто используя что-то вроде:

sub my_sub {
    my $ref_array = shift;
    for (@$ref_array) {
      #do somthing with $_ here
    };

    #use $ref_array->[$element] here
}

Однако в этом ответе один из местных монахов SO предложил Христу:

sub my_sub {
  local *array = shift();
  #use @array here
}

Когда я спросил

В попытке выучить Perl среднего уровня магия, могу я спросить, что это ты настраиваете на что здесь? Ты установка ссылки на @array для arrayref, который был передан в? Как знаете ли вы, что вы создаете @array и не% массив или $ массив? Где я могу узнать больше об этом * операторе (Perlop?). Спасибо!

Мне предложили спросить это как новый пост, хотя он дал хорошие ссылки. Во всяком случае, здесь идет? Может кто-нибудь объяснить, что присваивается тому, что и как получается, @array создается, а не% массив или $ массив? Благодаря.

Ответы [ 2 ]

22 голосов
/ 01 февраля 2011

Назначение глобу

*glob = VALUE

содержит магию, которая зависит от типа VALUE (т. Е. Возвращаемое значение, скажем, Scalar::Util::reftype(VALUE)).Если VALUE является ссылкой на скаляр, массив, хэш или подпрограмму, то только эта запись в таблице символов будет перезаписана.

Эта идиома

local *array = shift();
#use @array here

работает так, как задокументировано, когда первым аргументом подпрограммы является ссылка на массив.Если бы первым аргументом было, скажем, скалярное указание, тогда присвоение затронуло бы только $array, а не @array.

Небольшой демонстрационный скрипт, чтобы увидеть, что происходит:

no strict;

sub F {
  local *array = shift;

  print "\@array = @array\n";
  print "\$array = $array\n";
  print "\%array = ",%array,"\n";
  print "------------------\n";
}

$array = "original scalar";
%array = ("original" => "hash");
@array = ("orignal","array");

$foo = "foo";
@foo = ("foo","bar");
%foo = ("FOO" => "foo");

F ["new","array"];        # array reference
F \"new scalar";          # scalar reference
F {"new" => "hash"};      # hash reference
F *foo;                   # typeglob
F 'foo';                  # not a reference, but name of assigned variable
F 'something else';       # not a reference
F ();                     # undef

Выход:

@array = new array
$array = original scalar
%array = originalhash
------------------
@array = orignal array
$array = new scalar
%array = originalhash
------------------
@array = orignal array
$array = original scalar
%array = newhash
------------------
@array = foo bar
$array = foo
%array = FOOfoo
------------------
@array = foo bar
$array = foo
%array = FOOfoo
------------------
@array =
$array =
%array =
------------------
@array = orignal array
$array = original scalar
%array = originalhash
------------------

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

3 голосов
/ 01 февраля 2011

С моим общепринятым знанием Perl, я рискну ответить. Оператор * назначает запись в таблице символов. Насколько я понимаю, @array,% array и $ array все ссылаются на одну и ту же запись таблицы символов для строки 'array', но на разные поля в этой записи: поля ARRAY, HASH и SCALAR. Таким образом, присвоение local *array = shift; фактически присваивает всю запись таблицы локальных символов для «массива» (включая поля ARRAY, HASH и SCALAR) тому, что было передано для использования в вызывающей стороне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...