Bod has asked for the wisdom of the Perl Monks concerning the following question:

Much as I thought my understanding of references was going well, again misunderstanding strikes and I seek your wisdom.

The following code is a bare-bones test and demonstration of the issue I am having. In the module's new method I read an array from a database which is simulated here by @columns.

package crmtest; use strict; use warnings; sub new { my ($class, $env) = @_; my @columns = ('one', 'two', 'three', 'four'); my $self = bless { 'env' => $env, 'column' => \@columns, # <-- Reference t +o an array given here }, $class; return $self; } sub add { my ($self, $fields) = @_; foreach my $field(@$self->{'column'}) { # <-- Not an AR +RAY reference here print $field . " -- " . $self->{'column'} . "\n"; # do stuff... } } 1;

Here is what I think is happening...
I put a reference to the @columns array into the blessed anonymous hash to which $self holds the reference. The constructor returns the reference to the anonymous hash.
Later on, in the add method I want to iterate over the array so I dereference the key in the anonymous hash using @$self->{'column'}

Except I get the error - Not an ARRAY reference at crmtest.pm line 18
So I added the print line and removed the dereferencing so I tried iterating over $self->{'column'} without the '@'. This tells me that both $field and $self->{'column'} are the same as I would expect and that they are both ARRAY(0xe3c1f0)

This is the code I am using to test the bare-bones of the module:

use strict; use warnings; use lib('.'); use crmtest; my $crm = crmtest->new('someenv'); my $cols = { 'col1' => 'something', 'col2' => 'anotherthing', 'four' => 'moretest', }; $crm->add($cols);
Am I not creating the reference to @columns properly or am I trying to dereference wrongly or I am completely missing how references work?

EDIT:
To test what I am doing I have tried an even simpler version:

my @columns = ('one', 'two', 'three', 'four'); my $ref = \@columns; print @$ref;
And that does exactly what I expected - prints out the array. So it seems I am not totally on the wrong track!

Replies are listed 'Best First'.
Re: Not an ARRAY reference error
by GrandFather (Saint) on Mar 28, 2021 at 23:05 UTC

    Try @{$self->{'column'}}. :-)

    Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond

      Thank you :)

      So I wasn't too far out with the (de)referencing...that's a relief!

      Would it be correct that @$self->{'column'} is trying to dereference $self first and then access the column key of the dereferenced value?

        Would it be correct that @$self->{'column'} is trying to dereference $self first ...

        My narrative would be that @$self->{'column'} is trying to dereference $self first as an array reference (it's not; it's a blessed hash reference).

        ... and then access the column key of the dereferenced value?

        Once the attempt to dereference a hash ref. as an array fails, that's it: parsing cannot continue. If parsing went on, it would have to deal with an expression equivalent to
            @some_array->{'column'}
        that makes no Perlish sense. Looked at another way, even if the proper hash reference dereferencing operator (the % sigil) were used, the expression would still make no sense (update: now; see Update below):
            %$self->{'column'}
        is equivalent to
            %some_hash->{'column'}

        Update: Well, actually... It dawned on me that a long time ago, in a Perliverse far, far away, this sort of expression did, briefly, enjoy some validity:

        Win8 Strawberry 5.8.9.5 (32) Mon 03/29/2021 3:40:28 C:\@Work\Perl\monks >perl -Mstrict -Mwarnings -l my %hash = qw(column vertical fence horizontal); print %hash->{'column'}; Using a hash as a reference is deprecated at - line 3. my @array = qw(column fence); print @array->[1]; Using an array as a reference is deprecated at - line 6. my $ar = \@array; print @$ar->[0]; Using an array as a reference is deprecated at - line 9. ^Z vertical fence column
        (Update: Changed 5.8 example to include array reference; hash reference assumed to work similarly.)

        As it was told to me, the history of this syntax is that it began as a bug and was elevated by use into a "feature." As you see, it persisted as late as Perl version 5.8, although even by then it was deprecated. By version 5.30, it was entirely extirpated:

        Win8 Strawberry 5.30.3.1 (64) Mon 03/29/2021 2:54:54 C:\@Work\Perl\monks >perl my %hash = qw(column vertical fence horizontal); print %hash->{'column'}; Can't use a hash as a reference at - line 3. Win8 Strawberry 5.30.3.1 (64) Mon 03/29/2021 2:55:26 C:\@Work\Perl\monks >perl my @array = qw(column fence); print @array->[1]; Can't use an array as a reference at - line 3.

        Of course, something like @$hash_reference has always been verboten.


        Give a man a fish:  <%-{-{-{-<

        A simple test is to try {@$self}->{'column'} and see if that gives the same result (it does).

        I tend to be explicit always in this sort of dereferencing context because I'm never quite sure without thinking about it and I assume most other people working with the code will do the same thing.

        Optimising for fewest key strokes only makes sense transmitting to Pluto or beyond
Re: Not an ARRAY reference error
by ikegami (Patriarch) on Mar 29, 2021 at 20:25 UTC

    You want

    @{ $self->{column} } # Infix notation
    or
    $self->{column}->@* # Postfix notation

    When using the infix dereferencing syntax, the braces can only be omitted when the block amounts to a simple scalar.

    @{ $ref } # ok Derefs $ref @$ref # ok Derefs $ref @{ $self->{column} } # ok Derefs $self->{column} @$self->{column} # XXX Derefs $self

    See Mini-Tutorial: Dereferencing Syntax.

    Seeking work! You can reach me at ikegami@adaelis.com