Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Using a hash with the @ sigil

by 1nickt (Canon)
on Jul 24, 2015 at 23:28 UTC ( [id://1136246]=perlquestion: print w/replies, xml ) Need Help??

1nickt has asked for the wisdom of the Perl Monks concerning the following question:

Hi all, in answering a question today I cam upon something that puzzled me. First:

$ perl -Mstrict -wle"my %hash; @hash{'array'} = 'foo';" Scalar value @hash{'array'} better written as $hash{'array'} at -e lin +e 1. $

... which is what I expected. But then:

$ perl -Mstrict -wle"my %hash; my @array; @hash{@array} = 'foo';" $

Why doesn't Perl have a warning for the latter case?

The way forward always starts with a minimal test.

Replies are listed 'Best First'.
Re: Using a hash with the @ sigil
by choroba (Cardinal) on Jul 24, 2015 at 23:41 UTC
    It's so called "hash slice".
    use warnings; use strict; use Data::Dumper; my @arr = qw( a b c ); my %h; @h{@arr} = (3, 4, 5); # @hash{keys} = values print Dumper(\%h); __END__ Output: $VAR1 = { 'c' => 5, 'b' => 4, 'a' => 3 };
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

      Thanks choroba and all the other monks who replied...

      The way forward always starts with a minimal test.
      Hash slices are useful, but assigning a scalar to them is less useful. Perl could warn in that case, but I don't know that it should.
      @hash{@array} = 'foo'; # converted to a 1-element list @hash{@array} = ('foo'); # equivalent @hash{@array} = ('foo', undef, undef); # equivalent @hash{@array} = ('foo', 'foo', 'foo'); # arguably should be equivalent
Re: Using a hash with the @ sigil
by AnomalousMonk (Archbishop) on Jul 24, 2015 at 23:50 UTC
    Why doesn't Perl have a warning for the [@hash{@array} = 'foo'] case?

    I would say because an empty hash slice assignment | index list is a perfectly valid thing. It's equivalent to
        $hash{$_} = 'foo' for @array;
    which also does not (and should not) warn.

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my %hash = qw(a 1 b 2); my @array; @hash{@array} = 'foo'; dd \%hash; ;; $hash{$_} = 'foo' for @array; dd \%hash; " { a => 1, b => 2 } { a => 1, b => 2 }


    Give a man a fish:  <%-(-(-(-<

Re: Using a hash with the @ sigil
by stevieb (Canon) on Jul 24, 2015 at 23:43 UTC

    Because you're effectively using a hash slice.

    What that does is the @ in front of the hash presents its keys. Then if any of the keys match any elements in the array, those values are returned:

    my %h = (1 => 'a', 2 => 'b', 3 => 'c'); my @a = (2, 3); my @b = @h{@a}; print "$_\n" for @b; __END__ b c

    -stevieb

Re: Using a hash with the @ sigil
by Paladin (Vicar) on Jul 24, 2015 at 23:42 UTC
    The later case is a hash slice, which is valid. See perldata
Re: Using a hash with the @ sigil
by 1nickt (Canon) on Jul 26, 2015 at 19:04 UTC

    Replying to myself for the archives ...

    Not more than a couple of days after posting this and learning from the replies, I had cause to use a hash slice in my work. In a sub that can be called with a single argument consisting of a single value or a list, I was returning a hashref of objects in all cases.

    Much better to return the object directly if the sub is called with a single value:

    return (scalar keys %data == 1) ? @data{ keys %data } : \%data;

    Very cool. Thanks again, monks.

    The way forward always starts with a minimal test.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1136246]
Approved by stevieb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (3)
As of 2025-07-19 23:59 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.