1

I'm working on a Perl Dancer2 webapp and stumbled across the situation that I have an array that contains arrays that contain an array in position 2. I pass a reference to that array to a sub and then iterate over the array (that contains arrays).

When I try to get the innermost array inside a foreach() loop with @$$_[2], I get an error:

Not a SCALAR reference

I can easily work around this with:

my $ref = $$_[2];
print "@$ref\n";

but I wonder why the first approach doesn't work.

Have a look at my minimal example:

my @x = (["a", "b", [1, 2], "c"],
         ["x", "y", [8, 9], "z"]);
my $y = \@x;

foreach (@$y) {
#   print "@$$_[2]\n"; #produces error

    my $z = $$_[2];
    print "@$z\n"; #works
}

Any ideas what is going on here?

3
  • Possible duplicate of Perl, dereference array of references Commented Nov 20, 2015 at 17:18
  • You have an answer. But I'd be very interested to know where you picked up that horrible referencing syntax. Most places only mention it in passing on their way to the more readable (and less confusing) $_->[2] syntax. Commented Nov 21, 2015 at 15:45
  • @DaveCross I think it was the first syntax I saw reading the perldoc about referencing: link and I found it kind of intuitive... personally, I don't find $$_[2] more or less confusing than $_->[2] but rather a matter of habit Commented Nov 21, 2015 at 23:22

2 Answers 2

5

You need curly braces:

@{$$_[2]}

or, more readable

@{ $_->[2] }

The original @$$_[2] is interpreted as

@{ $$_ }[2]

Cf.

use feature qw{ say postderef };

$_ = [['a'], ['b'], ['c', 'd']];
say for @{ $_->[2] };
say for $_->[2]->@*;

$_ = \[ @$_ ];
say @$_ for @{ $$_ }[2];
say @$_ for $_->$*->[2];
Sign up to request clarification or add additional context in comments.

1 Comment

Ok, got it! Thank you :)
0

Look at the -> operator. Likely the problem is the brackets. After all, when you say $$_[2] do you mean: ${$_}[2] or {$$_}[2].

Something like this is probably clearer (assuming you want the 1,2 and 8,9)

#!/usr/bin/env perl
use strict;
use warnings;
use Data::Dumper;

my @x = ( [ "a", "b", [ 1, 2 ], "c" ], 
          [ "x", "y", [ 8, 9 ], "z" ] );
my $y = \@x;

print Dumper $y;

foreach my $array_ref (@$y) {
    print Dumper $array_ref;
    my $z = $array_ref->[2];
    print "@$z\n";
}

Comments

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.