Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
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 studying the Monastery: (3)
As of 2024-04-26 06:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found