контекст списка perl хеш-ссылок - PullRequest
2 голосов
/ 17 декабря 2010

Почему это работает? это строка 2

DB<1> $a = {'a'=>1}; $b = {'a'=>2, 'b'=>0};
DB<2> $c = ($a, $b);
DB<3> print $c;
  HASH(0x8743e68)
DB<4> print $c->{a},$c->{b};
  20

Я понимаю, что если бы я осторожно использовал% $ a и% $ b, Perl знал бы, что я имел в виду, но с просто голыми ссылками в списке, почему это работает?

Или, может быть, это выглядит так, как будто это работает, и я действительно сделал что-то еще?

1 Ответ

13 голосов
/ 17 декабря 2010

В

$c = ($a, $b);

отсутствует контекст списка. Вместо этого вы видите оператор запятой в действии:

Binary ","является оператором запятой.В скалярном контексте он оценивает свой левый аргумент, отбрасывает это значение, затем оценивает свой правый аргумент и возвращает это значение.Это похоже на оператор запятой C.

Чтобы увидеть это более четко, взгляните на:

#!/usr/bin/perl
use strict; use warnings;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z = ($x, $y);

print "\$x = $x\t\$y = $y\t\$z = $z\n";

my @z = ($x, $y);
print "@z\n";

Сначала я использовал warning .Поэтому, когда я запускаю этот скрипт, я получаю предупреждение:

Useless use of private variable in void context at C:\Temp\t.pl line 7.

Всегда Включить предупреждения.

Теперь вывод показывает, что происходит:

$x = HASH(0x39cbc)      $y = HASH(0x39dac)      $z = HASH(0x39dac)
HASH(0x39cbc) HASH(0x39dac)

Очевидно, $z относится к тому же анонимному хешу, что и $y.Копирование значений не производилось.

И, $z[0] относится к тому же анонимному хешу, что и $x, а $z[1] относится к тому же анонимному, что и $y и $z.

Обратите внимание, что одни только скобки не создают контекст списка.В случае

my @z = ($x, $y);

они необходимы, поскольку = связывается более плотно, чем оператор запятой.

my @z = $x, $y;

назначит $x на $z[0] и отбросит $y (и выдает предупреждение), тогда как

my @z = 1 .. 5;

будет работать как ожидалось.

Наконец, если вы хотите назначить $z новый анонимный хеш, который содержит копии анонимных хешейна что указывают $x и $y, вы должны сделать

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z = { %$x, %$y };

print Dumper $z;

, который выведет:

$VAR1 = {
          'a' => 2,
          'b' => 0
        };

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

#!/usr/bin/perl
use strict; use warnings;
use Data::Dumper;

my $x = {a => 1};
my $y = {a => 2, b => 0};

my $z;

push @{ $z->{$_} }, $x->{$_} for keys %$x;
push @{ $z->{$_} }, $y->{$_} for keys %$y;

print Dumper $z;

Вывод:

VAR1 = {
         'a' => [
                  1,
                  2
                ],
         'b' => [
                  0
                ]
       };
...