mswanberg
mswanberg

Reputation: 1285

Anonymous Hash Slices - syntax?

I love hash slices and use them frequently:

my %h;
@h{@keys}=@vals;

Works brilliantly! But 2 things have always vexed me.

First, is it possible to combine the 2 lines above into a single line of code? It would be nice to declare the hash and populate it all at once.

Second, is it possible to slice an existing anonymous hash... something like:

my $slice=$anonh->{@fields}

Upvotes: 10

Views: 1603

Answers (3)

ysth
ysth

Reputation: 98398

For your first question, to do it in a single line of code:

@$_{@keys}=@vals for \my %h;

or

map @$_{@keys}=@vals, \my %h;

but I wouldn't do that; it's a confusing way to write it.

Either version declares the variable and immediately takes a reference to it and aliases $_ to the reference so that the hash reference can be used in a slice. This lets you declare the variable in the existing scope; @{ \my %h }{@keys} = @vals; also "works", but has the unfortunate drawback of scoping %h to that tiny block in the hash slice.

For your second question, as shown above, slices can be used on hash references; see http://perlmonks.org/?node=References+quick+reference for some easy to remember rules.

my @slice = @$anonh{@fields};

or maybe you meant:

my $slice = [ @$anonh{@fields} ];

but @slice/$slice there is a copy of the values. To get an array of aliases to the hash values, you can do:

my $slice = sub { \@_ }->( @$anonh{@fields} );

Upvotes: 8

ikegami
ikegami

Reputation: 386501

  • First question:

    my %h = map { $keys[$_] => $vals[$_] } 0..$#keys;
    

    or

    use List::MoreUtils qw( mesh );
    
    my %h = mesh @keys, @vals;
    
  • Second question:

    If it's ...NAME... for a hash, it's ...{ $href }... for a hash ref, so

    my @slice = @hash{@fields};
    

    is

    my @slice = @{ $anonh }{@fields};
    

    The curlies are optional if the reference expression is a variable.

    my @slice = @$anonh{@fields};
    

Upvotes: 9

mob
mob

Reputation: 118665

Hash slice syntax is

@ <hash-name-or-hash-ref> { LIST }

When you are slicing a hash reference, enclose it in curly braces so it doesn't get dereferenced as an array. This gives you:

my @values = @{$anonh}{@fields}

for a hash reference $anonh.

Upvotes: 3

Related Questions