1

Here is what my module looks like:

#!/usr/bin/perl
package Page;

use strict;
use warnings;

use base qw/DBObj/;

our %fields = (
  id => undef,
  title => '$',
  content => '$'
);

sub get_field_names {
  my @names = sort keys \%fields;

  return \@names;
}

for my $field ( keys %fields ) {
  my $slot = __PACKAGE__ ."::$field";
  no strict "refs";

  *$field = sub {
    my $self = shift;
    $self->{$slot} = shift if @_;
    return $self->{$slot};
  }
}

1;

Here the parent module where the strange behaviour occurs

#!/usr/bin/perl
package DBObj;

use strict;
use warnings;

use Data::Dumper;

use DBConn;

sub new {
  my $me = shift;
  my $class = ref $me || $me;

  my $self = {
    dbh => new DBConn->new(
        dns => '/db.sql',
        user => '',
        pass => '',
      )
  };

  return bless $self, $class;
}

sub save {
  my $self = shift;

  my @field_names = @{$self->get_field_names};

  print Dumper @field_names;

  foreach my $item ( reverse @field_names ) {
    print $item;
  }
}
sub fill {
  my ( $self, $args ) = @_;

  foreach my $key ( keys $args ) {
    $self->$key( $args->{$key} );
  }
}

1;

here is what I am experiencing. This snippet

my @field_names = $self->get_field_names;

print Dumper @field_names;

foreach my $item ( reverse @field_names ) {
    print $item;
}

Data::Dumper shows

$VAR1 = [
          'content',
          'id',
          'title'
        ];

But the foreach loop returns

ARRAY(0x7fc750a26470)

I have a Test::Simple test case where I perform the following test

ok( shift $page->get_field_names eq 'content', 'Page has field content');

so I can shift off an item from the array, but I cannot loop through it which is a puzzle to me.

And please; before you tell me that I shouldn't be doing this and that there is a ton of modules out there I should pick instead, I want to point out; I am doing this our of pure fun, I have been away from Perl for ~10 years and thought it would be fun to play around with it again.

2 Answers 2

7

You have made get_field_names return a reference to an array, but you are then putting that reference into an array variable.

Try:

my $field_names = $self->get_field_names;

print Dumper $field_names;

foreach my $item ( reverse @$field_names ) {
    print $item;
}
Sign up to request clarification or add additional context in comments.

3 Comments

this results in the following "Global symbol "$field_names" requires explicit package name at ../modules/DBObj.pm line 34." that's not working out of the box
Which line of the above is line 34 in your script? Did you change my @field_names = ... to my $field_names = ...?
Sorry, I made a mistake when I altered my code. Your example works
1

get_field_names returns an arrayref, not an array. Either change its return type by removing the backslash from return \@names; or "cast" its return type to an array by writing:

my @field_names = @{$self->get_field_names};

2 Comments

Perl subroutines cannot return an array, only a list. And that isn't “casting”, it's dereferencing.
This works, I used @{$self->get_field_names}; and it now prints each item in the array - thanks. If I remove the backslash nothing is being printed inside the foreach

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.