2
use strict;

my $anon = [1,3,5,7,9];
my $aref  = [\$anon];

print "3rd element: "  . $ { $aref } [2] . "\n";

I'd like to get the nth element of the anonymous array $anon over the $aref variable. In the code I wanted to get the 3rd element of $anon by making the index 2 but it returned nothing. If I write $ { $aref } [0] then it returns something like REF(0x7fd459027ac0)

How can I get the nth, for example the 3rd element of $anon ?

Rationale:

my @area = (
    qw[1 3 5 7 9],
    qw[2 4 6 8 0],
    qw[a e i u o],
    qw[b c d f g]
    );

foreach my $row (@area) {
    foreach my $cell (@$row)
    {
    # do some processing on the element
    print $cell . " ";
    }
    print "\n";
}
HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
Terry
  • 1,206
  • 1
  • 10
  • 26
  • *"the nth element of the anonymous array `$anon` over the `$aref` variable"* What does *"over the `$aref` variable"* mean? – Borodin May 03 '18 at 01:37
  • *"I wanted to get the 3rd element of $anon by making the index 2 but it returned nothing"* No subroutine can return *nothing* and no variable can contain *nothing*. What do you mean here? – Borodin May 03 '18 at 01:39
  • 1
    `[ LIST ]` is basically short for `do { my @a = LIST; \@a }`, so you have `my @x = (1,3,5,7,9); my $anon = \@anon; my $y = \$anon; my @z = ($y); my $aref = \@z;` and you would need `${ ${ ${ $aref }[0] } }[2]` or `$aref->[0]->$*->[2]` for that wacky data structure. Of course, you should be using `my @array = (1,3,5,7,9); my $anon = \@array;` with `$ { $aref } [2]` or `$aref->[2]`. – ikegami May 03 '18 at 02:24
  • @Borodin What does "over the $aref variable" mean? Sorry for the late reply (I had to go bed after I posted the question) I mean iterating over the `$anon` using another variable such as `$aref` so that I can loop over and process the elements of `$anon` – Terry May 03 '18 at 06:58
  • @Borodin No subroutine can return nothing and no variable can contain nothing. What do you mean here? I meant space. On the console output, it returned without any error but because it didn't output any element I called it simply nothing. – Terry May 03 '18 at 07:38
  • The way you changed the code now invalidates the answers. What you have there now is just an array. `qw()` returns a list of quoted words. The fact that you chose `[` as the delimiter doesn't make that list an array reference. Your `@area` will just be a flat array with elements `1, 3, 5, 7, 9, 2, 4, 6, 8, 0, 'a', 'e', ...`. – simbabque May 03 '18 at 09:07
  • @simbabque How to make the words returned by `qw( )` arrays and/or array references so that I can access for instance `1, 3, 5, 7, 9` , `2, 4, 6, 8, 0` separately? How to avoid making a flat array meanwhile? – Terry May 03 '18 at 09:20
  • 1
    `my @foo = ( [ qw/a b c/ ], [ qw/1 2 3/ ], ... )` – you should really read [perlreftut](http://perldoc.perl.org/perlreftut.html). – simbabque May 03 '18 at 09:21
  • @simbabque Actually I read Programming Perl 4th edition, particularly the 8th chapter called 'References'. That part which you added square brackets to `qw/a b c/` expressions seems to solve the problem. The 8th chapter of the book and the perlreftut just didn't give information on that particular case, i.e. how to make `qw( )` block a distinct array. – Terry May 03 '18 at 09:56
  • `qw()` is not a block. In programming, the right terminology is very important, so we know what we're talking about. `qw()` returns a _list_. And a list is not an array either in Perl. Essentially you can assign the list to an array variable, and you can stick a list into an anonymous array reference, but you cannot take the reference of a list. Give it some practice and you'll quickly get the hang of this. Knowing when to use `[]`, `{}` or neither and how to stick those into each other will come naturally after a while. :) – simbabque May 03 '18 at 09:58
  • Also take a look at https://stackoverflow.com/a/14006130/1331451 and https://stackoverflow.com/a/6024268/1331451 and https://www.effectiveperlprogramming.com/2010/01/whats-the-difference-between-a-list-and-an-array/. – simbabque May 03 '18 at 10:01
  • 1
    @simbabque I took a look at the links; they're so helpful. so it seems I basically got stuck trying to take a reference of the list returned by `qw( )` The trick is to enclose `qw` in brackets (in par with your previous comment) and I couldn't find it though I browsed various posts, articles, tutorials. – Terry May 03 '18 at 10:44
  • Well the point is, you cannot take a reference of a list. You stick a list into an anonymous array reference. The list is just several pieces of information together, while an array is giving them a name, and a reference to an array is turning that array into a scalar pointer-like thing that you can pass around without copying all the values in the array all the time. – simbabque May 03 '18 at 10:56
  • It would help if we knew what you were trying to do with the data. Looking at the data structure you provided, it reminds me a lot of [Spreadsheet::ParseExcel](https://metacpan.org/pod/Spreadsheet::ParseExcel) where you use two arrays to loop through the rows and columns of a spreadsheet to determine the coordinates of each cell. Take a look at the synopsis of the module and see if it's close to what you're trying to accomplish. – interduo May 03 '18 at 19:01

2 Answers2

4

How can I get the nth element of a dereferenced anonymous array?

You have too many reference to operators. You have built a nested structure three levels deep and it's no wonder you're having trouble navigating it

The problem is that your $anon is already a reference to an anonymous array. Square brackets [...] construct an anonymous array and return a reference to it

You then have

my $aref  = [\$anon]

which creates another reference to an array with one element: a reference to the scalar $anon.

So you have built this

$anon = [1, 3, 5, 7, 9]

$aref = [ \ [1, 3, 5, 7, 9] ]

So

${$aref}[0]          is \ [1, 3, 5, 7, 9]
${${$aref}[0]}       is [1, 3, 5, 7, 9]
${${${$aref}[0]}}[2] is 5

But why are you working with references to arrays at all, and especially references to scalars? It would be best to begin with an ordinary array, and write

my @array = ( 1, 3, 5, 7, 9 );
my $aref = \@array;

print $aref->[2];

output

5
Borodin
  • 126,100
  • 9
  • 70
  • 144
  • Thank you for the reply. I added the rationale. I'd like to iterate over the array elements of an array inside a loop so that I can process them. I have to use `qw` to make it look simple and readable, but when I use `qw`, it looks like the array becomes anonymous. I'd like to iterate over those anonymous arrays and their elements. – Terry May 03 '18 at 07:51
1

You have a classic list-of-lists data structure, with a twist. You need to fetch the first element of the outer array reference, given by $aref, dereference the result, and then fetch the nth element of the inner array reference returned by that expression. This should do the trick:

${ $aref->[0] }->[2]

You may want to read through perllol and possibly even perlref for more information and ideas. If you have control over this data structure, there are better ways to build it. For example, if it were built like so:

my $anon = [1, 3, 5, 7, 9]; # a reference to an anonymous array
my $aref = [$anon]; # a reference to an anonymous array containing only the above reference

You could simply do:

$aref->[0][2]
mwp
  • 8,217
  • 20
  • 26
  • Please check your code before posting. `$aref->[0]` is the *scalar* `\$anon` and won't take kindly to being indexed. Your suggestion will cause a ***Not an ARRAY reference*** warning. You should think twice if the answer to a question seems obvious. – Borodin May 03 '18 at 01:33
  • Ah, I missed the double reference. Thanks @Borodin. I've updated my answer. – mwp May 03 '18 at 01:47
  • Thank you for the reply. I added the rationale behind my question. I'd like to iterate over the array elements of an array inside a loop so that I can process them. I have to use `qw` to make the arrays look simple and readable, but when I use `qw`, it looks like the array becomes anonymous. That's why I tried to get the nth element of those anonymous arrays using a dereference operator. – Terry May 03 '18 at 07:54
  • @Romario In your updated example, you actually end up with a one-dimensional, flattened array. I suggest you use something like Data::Dumper to inspect your data structures to see what's actually happening. `use Data::Dumper; die Dumper(\@area);` My advice about reading perllol stands! – mwp May 03 '18 at 08:01
  • @mwp Yes it's kind of a one-dimensional array and I just can't do any proper iteration yet operation on it. I've tried making it like http://oi65.tinypic.com/307qnox.jpg (screenshot) but still got difficulties iterating. I had added Data::Dumper but couldn't get any useful information of it so I gave up using it. – Terry May 03 '18 at 08:46