http://qs321.pair.com?node_id=253779


in reply to Re: How to connect more arrays to a new array
in thread Find unique elements from multiple arrays

Hi -

I'm totally baffled about what this section does:

++@h{@a,@b,@c,@d};
I tried this to peer into the hash:
while ( my ($k, $v) = each %h ) { print "$k:$v.\n"; }
And I just got a bunch of uninitialized value warnings. How does that statement work, and what does it do?

Replies are listed 'Best First'.
Re: Care to explain ++@h{@a,@b,@c,@d}; ?
by Ovid (Cardinal) on Apr 28, 2003 at 18:47 UTC

    The @h{@a,@b,@c,@d} syntax is a hash slice and it returns a list of all values in %hash that corresponds to keys represented by the array elements. It will auto-vivify elements that do not exist (hence your "uninitiliazed value" warnings). The preincrement operator is apparently taking the final element of the list and incrementing it. In other words, this is an obfuscated way of incrementing a single hash value, but with the side effect of auto-vivifying others. The following code snippet demonstrates:

    use strict; use warnings; use Data::Dumper; $Data::Dumper::Indent = 1; my %hash = ( foo => 1, bar => 2, baz => 3, quux => 4 ); my @a = qw(foo bar asdf); my @b = qw(baz); ++@hash{@a,@b}; print Dumper \%hash;

    That auto-vivifies $h{asdf} and increments $h{baz} to 4.

    Cheers,
    Ovid

    New address of my CGI Course.
    Silence is Evil (feel free to copy and distribute widely - note copyright text)

      And here I just thought that BrowserUK had made a mistake by applying the scalar context to the hash slice. I would have been quite happy if it had been been written as @h{@a,@b,@c,@d} = () since that is clear on maintaining the list/list context. It also assigns "nothing" to each hash which is correct. So I'd use it in the amended form for production code.

Re: Care to explain ++@h{@a,@b,@c,@d}; ?
by Aristotle (Chancellor) on Apr 28, 2003 at 18:52 UTC
    Well, you know what
    $hash{"key"}
    does - give you access to the value stored in the hash under that key. In the same way, you can say
    @hash{"key1", "key2"}
    which gives you access to an entire list of values, indexed by the given keys. This is called a slice (and exists, in analogous form, for arrays too). Now, when you assign to that list, regardless of how many values you provide, all of the keys in the list pop into existence as entries in the hash. If there are not enough values given, any extraneous keys are assigned the undefined value. So
    ++@h{@a,@b,@c,@d};
    leads to all of the values stored in @a etc being forced to become keys of the hash %h. And because hash keys cannot be duplicated, the list of keys for the resulting hash contains only one instance of each unique element from the arrays used as keys. I personally strongly prefer to write it as
    @h{@a,@b,@c,@d} = ();
    For all intents and purposes the effect is the same, it just doesn't look nearly as confusing as the ++ operator on the other one.

    Makeshifts last the longest.

Re: Care to explain ++@h{@a,@b,@c,@d}; ?
by BrowserUk (Patriarch) on Apr 28, 2003 at 20:17 UTC

    I was part way through a long-winded explaination when the latest episode of Enterprise came on. In the meantime the other respondants have explained it much better than I was.

    The only addition I would make is that the ++ serves only one purpose, that of inhibiting the "Useless use of hash slice in void context" warning message that results were it not there. I agree with Aristotle that assigning an empty list is a much clearer way of acheiving this, and is the way I will do this in future.

    An added bonus is that for anything other than the smallest datasets, it is slightly more efficient.


    Examine what is said, not who speaks.
    1) When a distinguished but elderly scientist states that something is possible, he is almost certainly right. When he states that something is impossible, he is very probably wrong.
    2) The only way of discovering the limits of the possible is to venture a little way past them into the impossible
    3) Any sufficiently advanced technology is indistinguishable from magic.
    Arthur C. Clarke.
Re: Care to explain ++@h{@a,@b,@c,@d}; ?
by dragonchild (Archbishop) on Apr 28, 2003 at 19:11 UTC
    @x{@y} = @z; means the same thing as:
    foreach my $i (0 .. $#y) { $x{$y[$i]} = $z[$i]; }
    By extension, ++@x{@y}; means (roughly) the same thing as:
    for my $i (0 .. $#y) { $i == 0 ? $x{$y[$i]} = 1 : $x{$y[$i]} = undef; }
    Does that make sense now?

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.