Понимание нажатия на хеш и конструкцию || = []. (сгенерировано в файле steamplate.t) - PullRequest
6 голосов
/ 21 ноября 2011

Я заново знакомлюсь с Perl и только что использовал module-starter для инициализации нового проекта.Я сейчас пытаюсь понять сгенерированный код.Все в порядке, кроме указанной ниже строки:

sub not_in_file_ok {
  my ($filename, %regex) = @_;
  open( my $fh, '<', $filename )
    or die "couldn't open $filename for reading: $!";

  my %violated;

  while (my $line = <$fh>) {
    while (my ($desc, $regex) = each %regex) {
        if ($line =~ $regex) {
            ##I'm having problems here
            push @{$violated{$desc}||=[]}, $.;
        }
    }
  }
  ...
}

У меня две проблемы:

  1. ||=[].За этим | следует |=, или это или ||, за которым следует =[].Может кто-нибудь рассказать мне, что здесь происходит?(Я предполагаю, что «если хеш пуст, создайте пустой анонимный массив для инициализации хэша», но я изо всех сил пытаюсь увидеть, как это формируется из кода.)это означает «присвоить номер строки ключу $desc для хэша %violated. Но из прочитанного мною кода» найдите значение ключа desc из $violated{$desc} (часть $violated{$desc}),затем используйте это значение как символическую ссылку на массив (часть @{$value}), затем вставьте номер строки в этот массив ". Я не вижу, как согласовать эти два представления.

Я думаю, мне есть чему поучиться в этой строке кода - может ли кто-нибудь помочь мне, пройдя через это?

Ответы [ 2 ]

8 голосов
/ 21 ноября 2011
  • ||=: это оператор присваивания .Пример

    $a ||= $b;
    # corresponds to
    $a = $a || $b;
    

    см. man perlop.В вашем примере

    $a ||= [];
    # corresponds to
    $a = $a || [];
    

    , то есть: если левый операнд ничем не определен, в противном случае присвойте пустую ссылку на массив

  • %violated содержит ссылку на массив длякаждое значение.Вы можете видеть это так:

    my $array_ref = $violated{$desc};
    push @{array_ref}, $.;
    

Более подробно написано:

  if (! $violated{$desc} ) {
      $violated{$desc} = [];
  }
  my $array_ref = $violated{$desc};
  push @{ $array_ref }, $.;

РЕДАКТИРОВАТЬ

Массивы иссылки на массив

  • массив, построенный с () и содержащий динамический упорядоченный список элементов (в Perl массивы могут динамически расти)

  • anссылка на массив - это ссылка на массив (более или менее указатель без арифметики указателя).Вы можете создать ссылку на массив с помощью []

Пример

my @a = ( 1, 2, 3);
# $a[0] will contain 1

my $array_ref = [ 10, 11, 12 ];
# array_ref is a _pointer_ to an array containing 10, 11 and 12

Чтобы получить доступ к ссылке на массив, необходимо разыменовать ее:

@{ $array_ref };

my @array = @{ $array_ref }; # is valid

Вы можете получить доступ к { $array_ref} в виде массива

${ $array_ref }[0]

Теперь вернемся к вашему вопросу в комментарии: %violated - это хеш со следующими парами ключ-значение: строка ($ desc) иссылка на массив

3 голосов
/ 21 ноября 2011

Давайте попробуем разобрать этот шаг за шагом:

  1. Строка используется для заполнения хеша arrayrefs, где arrayrefs содержат номера строк, где регулярное выражение $descМатчи.Результирующий хеш %violated будет выглядеть примерно так:

    ( desc1 => [ 1, 5, 7, 10 ], desc2 => [ 2, 3, 4, 6, 8 ] );

  2. push принимает массив в качестве первого аргумента.Переменная $violated{$desc является ссылкой на массив, а не массивом, поэтому для ее разыменования используется @{...} (разыменование является противоположностью ссылки).

  3. Теперь для сложной части.Содержимое внутри фигурных скобок - это просто причудливый способ сказать, что если $violated{$desc} не определено внутри %violated (протестировано с ||), то оно присваивается (=) пустой ссылке на массив ([]).Думайте об этом как о двух назначениях в одной строке:

    $violated{$desc} = $violated{$desc} || [];

    push @{$violated{$desc}}, $.;

  4. Обратите внимание, что это осложнение обычно не является необходимым,благодаря функции под названием autovivification, которая автоматически создает ранее неопределенные ключи внутри хеша с заданным контекстом (в данном случае это ссылка на массив).Единственный случай, который я могу придумать, где это понадобится, это если $violated{$desc} == 0 раньше.

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