2

I'm trying to assign an array to a value in my hash as follows:

$authors->[$x]->{'books'} = @books;

$authors is an array of hashes that contains his/her first name, last name, date of birth, etc. And now I'm creating a books key where I want to assign an array of books. However, when I try to print it afterwords, it's just printing the size of the array, as if I'm doing $value = scalar @books.

What am I doing wrong?

2 Answers 2

10

Array elements and hash values are scalars, so when you are nesting arrays and hashes, you must use references. Just as $authors->[$x] is not a hash but a reference to a hash, you must set $authors->[$x]->{'books'} to a reference to the array.

$authors->[$x]->{'books'} = \@books; # reference the original array
$authors->[$x]->{'books'} = [@books]; # reference a copy

You would then access elements of the array using something like

$authors->[$x]->{'books'}->[0]

which can be abbreviated

$authors->[$x]{books}[0]

or access the whole array as

@{$authors->[$x]{books}}

Your original attempt

$authors->[$x]->{'books'} = @books;

is exactly equivalent to

$authors->[$x]->{'books'} = scalar @books;

because the left operand of the = operator is a hash value, which is a scalar, so the right operand is evaluated in scalar context to provide something that can be assigned there.

P.S.

On rereading this answer I realized it may be confusing to say "a hash value is a scalar" because of the possible interpretation of "hash value" as meaning "the value of a hash variable" i.e. "the whole hash". What I mean when I write "hash value" is an item that is stored in a hash as a value (as opposed to a key).

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! That worked. What is the difference between "reference the original array" method versus "reference a copy" method? And what is meant by "reference"? Is this the same as in C?
@Ricky [ @books ] (you can call [ ]the anonymous array constructor) takes @books and makes a copy that can be held as a reference "anonymously". With \@books you are referring to the original array. This makes a difference if you change any of the elements - i.e.does it change the copy or the reference and the original? See perldoc perlreftut and perldoc perlref. There's many a handy guide/blog post comparing perl references and C pointers :-)
@Ricky Fire up the re.pl or the debugger and try: my @test1 = qw/ q w e r t y / ; my $test2 = \@test1 ; my $test3 = [ @test1 ]. Then pop an element from each of those $test2 and $test3 array references and see how it affects @test1.
2

While the first awnser is absolutely right, as an alternative, you could also fo this:

push @{$authors->[$x]->{'books'}}, @books;

Then $authors->[$x]->{'books'} will be an Array that contains a copy of all the elements from @books. This might be more "foolproof" then working with references, as mentioned above.

1 Comment

yes, your are right, its the same as $authors->[$x]->{'books'} = [@books]; # reference a copy. My bad, should have looked better at the other awnser.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.