Почему пустой хэш Perl имеет один ключ? - PullRequest
8 голосов
/ 12 апреля 2011

Стандартный гугл-ответ «Как узнать размер хэша в Perl?» это «принять размер keys(%hash)»:

my %h = {};
print scalar (keys (%h));

Это печатает '1'. Я ожидал ноль. С другой стороны. Точно так же,

my %h = {};
$h{"a"} = "b";
$h{"x"} = "y";
print scalar keys (%h);
print "\nKey: $_" for (keys %h);

Печать:

3

Ключ:

Ключ: x

Ключ: HASH (0x229e8)

Откуда взялась эта дополнительная ценность?

Ответы [ 4 ]

24 голосов
/ 12 апреля 2011
$ perl -Mwarnings -e'my %h = {}'
Reference found where even-sized list expected at -e line 1.

строгие и предупреждения включены в Perl по очень веским причинам.Нет причин не использовать их.

Еще лучше, добавьте в смесь диагностика :

$ perl -Mwarnings -Mdiagnostics -e'my %h = {}'
Reference found where even-sized list expected at -e line 1 (#1)
    (W misc) You gave a single reference where Perl was expecting a list
    with an even number of elements (for assignment to a hash). This usually
    means that you used the anon hash constructor when you meant to use
    parens. In any case, a hash requires key/value pairs.

        %hash = { one => 1, two => 2, };    # WRONG
        %hash = [ qw/ an anon array / ];    # WRONG
        %hash = ( one => 1, two => 2, );    # right
        %hash = qw( one 1 two 2 );      # also fine
21 голосов
/ 12 апреля 2011

Это меня и раньше раздражало.

my %h = ();

Обратите внимание на использование () вместо {}.

Объяснение: Значение {} равно ссылка на хеш, а не на сам хеш.В Perl ссылка является своего рода скалярным значением, а присвоение %h имеет специальную обработку для присвоения одного скалярного значения.Он структурирует скаляр (давая вам строку HASH(0x229e8) в вашем случае) и связывает этот ключ со значением undef.

При использовании () присвоение из списка хешу создает ключ / значениепары из пар в списке, и поскольку () пусто, хеш %h становится пустым.

7 голосов
/ 12 апреля 2011

{} является ссылкой на анонимный хеш.Так что my %h = {} эквивалентно моему %h = ({} => undef).

Perl требует, чтобы ключи хеша были строками, поэтому, когда вы используете ссылку в качестве ключа, Perl использует строковое представление ссылки (HASH(0x229e8)).

6 голосов
/ 12 апреля 2011
use Data::Dumper;

my %h = {};
warn Dumper \%h;

%h назначается с хэш-ссылкой в ​​качестве ключа и undef в качестве значения.

Выход:

$VAR1 = {
          'HASH(0x8683830)' => undef
        };

Как Рафл предположил, что прагма warnings поймала бы это.Посмотрите на Грег Хьюгилл ответ для исправленного кода.

...