Почему Perl обрабатывает хеш-элемент как список списка при объявлении? - PullRequest
3 голосов
/ 25 февраля 2010

Учитывая этот код:

#!/usr/bin/perl -w

use strict;
use warnings;

sub foo {
    return wantarray ? () : "value1";
}

my $hash = {
    key1 => foo(),
    key2 => 'value2'
};

use Data::Dumper;
print Dumper($hash);

Я получаю следующий вывод:

$VAR1 = {
  'key1' => 'key2',
  'value2' => undef
};

Когда я ожидал:

$VAR1 = {
  'key1' => 'value1',
  'key2' => 'value2'
};

Я понимаю, что хеш - это своего рода массив четного размера (о чем свидетельствует предупреждение «Нечетное количество элементов в назначении хеша»), но хеш-элемент может быть только скалярным, почему компилятор дает ему контекст массива?

Я нашел это, используя функцию param модуля CGI при назначении непосредственно хешу. Вышеуказанная функция foo () была вызовом CGI :: param ('mistyped_url_param'), который возвращал пустой массив, разрушая (вращая?) Хеш-структуру.

Ответы [ 2 ]

7 голосов
/ 25 февраля 2010

Толстая запятая не является специальным оператором присваивания хеша. Это просто кусочек синтаксического сахара, что означает «автоцитировать предыдущую вещь»

Итак:

my $hash = {
    key1 => foo(),
    key2 => 'value2'
};

Средства:

my $hash = {
    'key1', foo(), 'key2', 'value2'
};

… который является списком и, как говорит Виллерт:

каждое выражение в списке оценивается в контексте списка. Вы можете обойти это, позвонив scalar foo()

3 голосов
/ 26 февраля 2010

Анонимный хеш-конструктор предоставляет контекст списка объектам внутри него, потому что он ожидает список ключей и значений.Это так, потому что так оно и есть.У нас нет способа представления хэша Perl в коде, поэтому вы должны использовать список, в котором мы чередуем ключи и значения.Обозначение => помогает нам визуально, но не выполняет никакой магии, которая помогает Perl выяснять хеш-виды.

Текущий контекст распространяется на вызовы подпрограмм и т. Д., Как и в любой другой ситуации.

Это позволяет вам создавать хэши с помощью операций со списком:

 my $hash = { 
      a => 'A',  
      map( uc, 'd' .. 'f' ),
      return_list( @args ), 
      z => 'Z' 
      };

Если вам нужно что-то в скалярном контексте, просто скажите, используя scalar:

 my $hash = { 
      a => 'A',  
      map( uc, 'd' .. 'f' ),
      'g' => scalar return_item( @args ), 
      z => 'Z' 
      };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...