What are anonymous hashes in perl?

房东的猫 提交于 2019-12-03 08:50:59

问题


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

What exactly do Perl's “anonymous hashes” do?


回答1:


It is a reference to a hash that can be stored in a scalar variable. It is exactly like a regular hash, except that the curly brackets {...} creates a reference to a hash.

Note the usage of different parentheses in these examples:

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

This is useful to be able to do, if you for example want to pass a hash as an argument to a subroutine:

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

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

And it is a way to create a multilevel hash:

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



回答2:


You use an anonymous hash when you need reference to a hash and a named hash is inconvenient or unnecessary. For instance, if you wanted to pass a hash to a subroutine, you could write

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

but if there is no need to access the hash through its name %hash you could equivalently write

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

This comes in handy wherever you need a reference to a hash, and particularly when you are building nested data structures. Instead of

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,
);

you can write just

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

and to add a member,

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

is a lot neater than

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

and of course, even if a hash is created with a name, if its reference is passed elsewhere then there may be no way of using that original name, so it must be treated as anonymous. For instance in

my $crew_member = $crew{bill}

$crew_member is now effectively a reference to an anonymous hash, regardless of how the data was originally constructed. Even if the data is (in some scope) still accessible as %person1 there is no general way of knowing that, and the data can be accessed only by its reference.




回答3:


It's quite simple. They allow you to write

push @hashes, { ... };

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

instead of

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

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

(If you want to know the purpose of references, that's another story entirely.)




回答4:


Anything "anonymous" is a data structure that used in a way where it does not get a name.

Your question has confused everyone else on this page, because your example shows you giving a name to the hash you created, thus it is no longer anonymous.

For example - if you have a subroutine and you want to return a hash, you could write this code:-

return {'hello'=>123};

since it has no name there - it is anonymous. Read on to unwind the extra confusion other people have added on this page by introducing references, which are not the same thing.

This is another anonymous hash (an empty one):

{}

This is an anonymous hash with something in it:

{'foo'=>123}

This is an anonymous (empty) array:

[]

This is an anonymous array with something in it:

['foo',123]

Most of the time when people use these things, they are really trying to magically put them inside of other data structures, without the bother of giving them a waste-of-time temporary name when they do this.

For example - you might want to have a hash in the middle of an array!

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

that array has 3 elements - the last element is a hash! ($array[2]->{foo} is 3)

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

Sometimes you want to don't want to pass around an entire data structure, instead, you just want to use a pointer or reference to the data structure. In perl, you can do this by adding a "\" in front of a variable;

%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 $$)

If you're crazy, you can even have references to anonymous hashes:

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

and sometimes perl is clever enough to know you really meant reference, even when you didn't specifically say so, like my first "return" example:

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

or:-

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


来源:https://stackoverflow.com/questions/14175585/what-are-anonymous-hashes-in-perl

工具导航Map

JSON相关