Question

Ok, I understand perl hash slices, and the "x" operator in Perl, but can someone explain the following code example from here (slightly simplified)?

sub test{
    my %hash;
    @hash{@_} = (undef) x @_;
}

Example Call to sub:

test('one', 'two', 'three');

This line is what throws me:

@hash{@_} = (undef) x @_;

It is creating a hash where the keys are the parameters to the sub and initializing to undef, so:

%hash:

'one' => undef, 'two' => undef, 'three' => undef

The rvalue of the x operator should be a number; how is it that @_ is interpreted as the length of the sub's parameter array? I would expect you'd at least have to do this:

@hash{@_} = (undef) x scalar @_;
Was it helpful?

Solution

To figure out this code you need to understand three things:

The repetition operator. The x operator is the repetition operator. In list context, if the operator's left-hand argument is enclosed in parentheses, it will repeat the items in a list:

my @x = ('foo') x 3;  # ('foo', 'foo', 'foo')

Arrays in scalar context. When an array is used in scalar context, it returns its size. The x operator imposes scalar context on its right-hand argument.

my @y = (7,8,9);
my $n = 10 * @y; # $n is 30

Hash slices. The hash slice syntax provides a way to access multiple hash items at once. A hash slice can retrieve hash values, or it can be assigned to. In the case at hand, we are assigning to a hash slice.

# Right side creates a list of repeated undef values -- the size of @_.
# We assign that list to a set of hash keys -- also provided by @_.
@hash{@_} = (undef) x @_;

Less obscure ways to do the same thing:

@hash{@_} = ();
$hash{$_} = undef for @_;

OTHER TIPS

In scalar context, an array evaluates to its length. From perldoc perldata:

If you evaluate an array in scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.)

Although I cannot find more information on it currently, it seems that the replication operator evaluates its second argument in scalar context, causing the array to evaluate to its length.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top