Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Hash initialization works, but why?

by throop (Chaplain)
on Jun 04, 2008 at 22:25 UTC ( [id://690266]=perlquestion: print w/replies, xml ) Need Help??

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

Brethren,

Here on perlmonks, I've picked up the nifty way of initializing a hash

@foo{1,2,3} = qw(a b c);
works the same as
%foo = ( 1 => 'a' 2 => 'b' 3 => 'c')
which has been very handy to me several times when I've had a pair of 'parallel' lists that I wanted to turn into a hash.
@foo{@keys} = @values; # instead of $foo{$_} = shift(@values) foreach @keys
But I don't understand why it works. I mean, @foo, %foo and $foo are three separate data-structures. @foo{@keys} = @values; looks like it's affecting @foo. But it isn't. It's affecting %foo.

Howscome?

I have an intuition that this has to do with (de)referencing of typeglobs, but I don't have nearly enough enlightenment. So I can copy the recipe by rote, but have insufficient insight into the Perl-nature of *foo.

throop

Replies are listed 'Best First'.
Re: Hash initialization works, but why?
by ikegami (Patriarch) on Jun 04, 2008 at 22:44 UTC

    But I don't understand why it works

    It's a hash slice.

    @foo{@keys} = @values; looks like it's affecting @foo. But it isn't. It's affecting %foo

    So $foo[0] affects $foo? No. The sigil indicates the value type, not the variable type. $foo[3] refers to the scalar value (thus the $) at element 3 of the array @foo.

    @foo{qw( 1 2 3 )} = qw( a b c ); works the same as %foo = qw( 1 a 2 b 3 c );

    Only if the hash is initially empty.

    my %foo = qw( a 1 b 2 ); my %bar = qw( a 1 b 2 ); %foo = qw( c 3 d 4 ); @bar{qw( c d )} = qw( 3 4 ); print(join(' ', %foo), "\n"); # c 3 d 4 print(join(' ', %bar), "\n"); # a 1 b 2 c 3 d 4

    I have an intuition that this has to do with (de)referencing of typeglobs

    No, no typeglobs involved, so it works equally well on lexical (my) variables as package (our) variables.

Re: Hash initialization works, but why?
by FunkyMonk (Chancellor) on Jun 04, 2008 at 22:29 UTC
    It's a hash slice and explained in perldata.

    Unless I state otherwise, all my code runs with strict and warnings
Re: Hash initialization works, but why?
by thparkth (Beadle) on Jun 04, 2008 at 22:52 UTC
    The short answer is that @array{1,2,3} is a hash slice, and therefore an array. You can tell it's a hash slice because the indexes are inside {curlies}. You can tell it's an array because it starts with an @.

    It's rather like the whole beginner array-vs-array-item confusion that so many people encounter, at least briefly: if @x is my array, surely item 3 in @x should be @x[3] ?

    But of course it's not, it's $x[3] because the item itself is a scalar.

    In this case, even though we're retrieving from (or in your case assigning to) a hash, we're interacting with it in a list-centric way rather than a one-thing-at-a-time way.

    So @x{...} refers to %x. It has nothing to do with @x at al, and also nothing to do with typeglobs.

    The trick is to understand that the kind of brackets around the index ({} vs []) determine whether it's an array or hash that you're dealing with, not the symbol at the front, which only determines how many things you're dealing with in one operation.

      The short answer is that @array{1,2,3} is a hash slice, and therefore an array

      That's wrong. It a hash slice, and it produces a list. It's not an array. Very different.

        I admit, I've always thought that 'array' was just Perl's particular jargon for 'list'. Or maybe "Perl's data-structure for holding a list." If I write
        @foo = (1,2,3)
        then @foo is an array, while (1,2,3) is a list. Right?

        I find myself still confused on the distinction between an array and a list. Could you explain more?

        throop

Re: Hash initialization works, but why?
by ysth (Canon) on Jun 05, 2008 at 02:48 UTC
    An important difference: The hash assignment clears the hash, then populates it from the key/value list. The hash slice assignment sets the values for the given keys (overwriting any previous value for those keys) but leaves any other data in the hash intact.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (6)
As of 2024-04-24 11:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found