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

Perl 的“匿名哈希”究竟做了什么?

4

4 回答 4

21

它是对可以存储在标量变量中的哈希的引用。它与常规散列完全一样,不同之处在于大括号{...}创建了对散列的引用

请注意这些示例中不同括号的用法:

%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"
于 2013-01-05T19:38:39.163 回答
13

当您需要引用散列并且命名散列不方便或不必要时,您可以使用匿名散列。例如,如果您想将哈希传递给子程序,您可以编写

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's cat" };

比整洁得多

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

当然,即使使用名称创建散列,如果将其引用传递到其他地方,则可能无法使用该原始名称,因此必须将其视为匿名。例如在

my $crew_member = $crew{bill}

$crew_member现在实际上是对匿名哈希的引用,无论数据最初是如何构造的。即使数据(在某些范围内)仍然可以访问,因为%person1没有一般的方法知道这一点,并且只能通过其引用访问数据。

于 2013-01-06T18:45:03.960 回答
5

这很简单。他们允许你写

push @hashes, { ... };

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

代替

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

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

(如果你想知道引用的目的,那就完全是另一回事了。)

于 2013-01-06T06:26:14.490 回答
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"]);'
$@array = [
            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
于 2016-08-28T12:06:30.470 回答