Perl: Assigning an array to a hash

48,706

Solution 1

The part you're missing is that @a = [1,2,3] doesn't make an array with 3 elements. It makes an array with one element which is an arrayref.

You meant @a = (1,2,3).

To assign that array to a hash element, you'd use either $b{"x"} = [@a] or $b{"x"} = \@a, depending on what you're trying to do. [@a] makes a new arrayref containing a copy of the current contents of @a. If the contents of @a change after that, it has no effect on $b{x}.

On the other hand, \@a gives you a reference to @a itself. If you then change the contents of @a, that will be visible in $b{x} (and vice versa).

Solution 2

You need to read the perlref documentation that talks about references.

There is a difference in how your arrays are stored:

# this is an array in an array variable
@a = (1, 2, 3);

Verses storing a reference to an array:

# this is an array in a scalar variable stored as a reference to the previous array:
$b = \@a;

Functionally that works like a pointer. Thus you can also store this reference in a hash:

$x{'something'} = \@a;

This all works just fine. What you haven't realized is that []s create references to an array, which you can't store in an array variable. You must store it in a scalar. Thus this instead:

$c = [1, 2, 3];
$x{'else'} = $c;

will work.

And accessing and modifying the array before you do the second assignment can be done using:

$c->[3] = '4';

or by using it in array form dereferencing it first

push @$c, 5;
Share:
48,706
Walt Stoneburner
Author by

Walt Stoneburner

Software engineer and many other things.

Updated on November 19, 2020

Comments

  • Walt Stoneburner
    Walt Stoneburner over 3 years

    This syntax works:

    $b{"x"} = [1,2,3];
    pp %b;
    # Displays ("x", [1, 2, 3]) 
    

    But I need to be able to dynamically create the array's contents and assign it later. This does not work; help, what's the obvious part I'm missing?

    @a = [1,2,3];
    $b{"x"} = @a;
    pp %b;
    # Shows up as ("x", 1) ... not what I want or expected.
    

    Tried these variations, too.

    $b{"x"} = [@a];  # ("x", [[1, 2, 3]])  ...close
    
    $b{"x"} = \@a;   # ("x", [[1, 2, 3]])  
    
    $b{"x"} = [\@a]; # ("x", [[[1, 2, 3]]])  
    
    $b{"x"} = %a;    # ("x", 0)
    
    $b{"x"} = $a;    # ("x", undef)
    
    $b{"x"} = [$a];  # ("x", [undef])
    
    $b{"x"} = @{@a};  # ("x", 0) 
    

    And, ideally, I'd like to be able to get the array back out later as an array.