Подтвердить что ты не робот

Что такое анонимные хэши в perl?

$hash = { 'Man' => 'Bill',
          'Woman' => 'Mary,
          'Dog' => 'Ben'
        };

Что именно делает Perl "анонимные хэши"?

4b9b3361

Ответ 1

Это ссылка на хэш, который может быть сохранен в скалярной переменной. Это как обычный хэш, за исключением того, что фигурные скобки {...} создают ссылку на хеш.

Обратите внимание на использование разных круглых скобок в следующих примерах:

%hash = ( foo => "bar" );   # regular hash
$hash = { foo => "bar" };   # reference to anonymous (unnamed) hash
$href = \%hash;             # reference to named hash %hash

Это полезно сделать, если вы, например, хотите передать хэш в качестве аргумента подпрограмме:

foo(\%hash, $arg1, $arg2);

sub foo {
    my ($hash, @args) = @_;
    ...
}

И это способ создания многоуровневого хэша:

my %hash = ( foo => { bar => "baz" } );  # $hash{foo}{bar} is now "baz"

Ответ 2

Вы используете анонимный хеш, когда вам нужна ссылка на хэш, и именованный хеш неудобен или ненужен. Например, если вы хотите передать хэш в подпрограмму, вы можете написать

my %hash = (a => 1, b => 2);
mysub(\%hash);

но если нет необходимости обращаться к хэшу через его имя %hash, вы можете равнозначно написать

mysub( {a => 1, b => 2} );

Это пригодится везде, где вам нужна ссылка на хэш, и особенно когда вы создаете вложенные структуры данных. Вместо

my %person1 = ( age => 34, position => 'captain' );
my %person2 = ( age => 28, position => 'boatswain' );
my %person3 = ( age => 18, position => 'cabin boy' );

my %crew = (
  bill => \%person1,
  ben  => \%person2,
  weed => \%person3,
);

вы можете написать просто

my %crew = (
  bill => { age => 34, position => 'captain' },
  ben  => { age => 28, position => 'boatswain' },
  weed => { age => 18, position => 'cabin boy' },
);

и добавить элемент,

$crew{jess} = { age => 4, position => "ship cat" };

намного опрятно, чем

my %newperson = ( age => 4, position => "ship cat" );
$crew{jess} = \%newperson;

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

my $crew_member = $crew{bill}

$crew_member теперь фактически является ссылкой на анонимный хеш, независимо от того, как данные были первоначально созданы. Даже если данные (в некоторой области) все еще доступны как %person1, нет общего способа узнать это, и к данным можно получить доступ только по его ссылке.

Ответ 3

Это довольно просто. Они позволяют вам писать

push @hashes, { ... };

f(config => { ... });

вместо

my %hash = ( ... );
push @hashes, \%hash;

my %config = ( ... );
f(config => \%config);

(Если вы хотите узнать цель ссылок, эта другая история полностью.)

Ответ 4

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

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

Например - если у вас есть подпрограмма, и вы хотите вернуть хэш, вы можете написать этот код: -

return {'hello'=>123};

так как там нет имени - это анонимно. Читайте дальше, чтобы расслабиться от лишней путаницы, которую другие люди добавили на эту страницу, введя ссылки, которые не то же самое.

Это еще один анонимный хеш (пустой):

{}

Это анонимный хеш с чем-то в нем:

{'foo'=>123}

Это анонимный (пустой) массив:

[]

Это анонимный массив с чем-то в нем:

['foo',123]

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

Например, вы можете захотеть иметь хэш в середине массива!

@array=(1,2,{foo=>3});

этот массив имеет 3 элемента - последний элемент - хэш! ($ array [2] → {foo} равно 3)

perl -e '@array=(1,2,{foo=>1});use Data::Dumper;print Data::Dumper->Dump([\@array],["\@array"]);'
[email protected] = [
            1,
            2,
            {
              'foo' => 1
            }
          ];

Иногда вы не хотите передавать всю структуру данных, вместо этого вы просто хотите использовать указатель или ссылку на структуру данных. В perl вы можете сделать это, добавив "\" перед переменной;

%hashcopy=%myhash;     # this duplicates the hash
$myhash{test}=2;       # does not affect %hashcopy
$hashpointer=\%myhash; # this gives us a different way to access the same hash
$hashpointer->{test}=2;# changes %myhash
$$hashpointer{test}=2; # identical to above (notice double $$)

Если вы сумасшедший, вы можете даже иметь ссылки на анонимные хэши:

perl -e 'print [],\[],{},\{}'
ARRAY(0x10eed48)REF(0x110b7a8)HASH(0x10eee38)REF(0x110b808)

и иногда perl достаточно умный, чтобы знать, что вы действительно имели в виду ссылку, даже если вы этого конкретно не сказали, например, мой первый пример возврата:

perl -e 'sub tst{ return {foo=>bar}; }; $var=&tst();use Data::Dumper;print Data::Dumper->Dump([\$var],["\$var"]);'     
$var = \{
       'foo' => 'bar'
     };

или: -

perl -e 'sub tst{ return {foo=>bar}; }; $var=&tst(); print "$$var{foo}\n$var->{foo}\n"'
bar
bar