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

I am having trouble trying to pass a hash as an argument to a module. Ultimately I want to use the hash as an index of column names, but for this post I'll just use toy code. I haven't written a module before and have been following this webpage for guidance:

https://www.perl.com/article/25/2013/5/20/Old-School-Object-Oriented-Perl/

My module code is:
1 package toy_module; 2 3 sub new { 4 my ($class, $args) = @_; 5 my $self = { 6 simple_hash => $args->{simple_hash}, 7 simple_test_scalar => $args->{simple_test_scalar}, 8 }; 9 print "********** INSIDE SUBROUTINE NEW **********\n"; 10 print "simple scalar: ".$self->{simple_test_scalar}."\n"; 11 print "$_\n" for keys %$self->{simple_hash}; 12 return bless $self, $class; 13 } 14 15 sub show_simple_hash { 16 my $self = shift; 17 print "********** INSIDE SUBROUTINE SHOW_SIMPLE_HASH ***** +*****\n"; 18 print "simple scalar: ".$self->{simple_test_scalar}."\n"; 19 print "$_\n" for keys %$self->{simple_hash}; 20 } 21 22 1;
And my code to call the module is:
1 use strict; 2 use warnings; 3 use lib '~/working/toys'; 4 use toy_module; 5 6 my %little_test_hash = ( 7 COL_1 => 0, 8 COL_2 => 1, 9 COL_3 => 2, 10 COL_4 => 3, 11 COL_5 => 4, 12 ); 13 my $little_test_hash_ref = %little_test_hash; 14 15 my $test_object = toy_module->new({simple_hash=>$little_test_hash_ +ref, simple_test_scalar=>5}); 16 my $next_test = $test_object->show_simple_hash;
What I hoped to see was the little_test_hash being passed along (and its keys printed) when test_object is instantiated by the subroutine "new", and then to see it preserved as an attribute (and its keys printed) when the subroutine "show_simple_hash" is called. Instead, this is what I get:
MacBook-Pro:toys mcrepeau$ perl test_toy_module.pl Using a hash as a reference is deprecated at toy_module.pm line 11. Using a hash as a reference is deprecated at toy_module.pm line 19. ********** INSIDE SUBROUTINE NEW ********** simple scalar: 5 Type of argument to keys on reference must be unblessed hashref or arr +ayref at toy_module.pm line 11.
Can anyone help me understand what I'm doing wrong?

Replies are listed 'Best First'.
Re: Trouble passing a hash to a module
by The Perlman (Scribe) on Aug 27, 2019 at 21:25 UTC
    This at least looks wrong

     $little_test_hash_ref = %little_test_hash;

    You should reference the hash with \%...

     $little_test_hash_ref = \%little_test_hash;

    - Ron
      That, or define it as a hashref in the first place.
      my $little_test_hash_ref = { COL_1 => 0, # ... };


      holli

      You can lead your users to water, but alas, you cannot drown them.
Re: Trouble passing a hash to a module
by jcb (Parson) on Aug 27, 2019 at 23:20 UTC

    As NetWallah mentioned, your hash dereference syntax is subtly wrong. The dereference operators bind very tightly, and also accept a BLOCK that evaluates to a reference. Where you have %$self->{simple_hash}, you should instead write %{$self->{simple_hash}}. The full details are in perlref. The warning about using a hash as a reference is produced when perl interprets %$self->{simple_hash} as %{$self}->{simple_hash}. The object you are using is stored as a hashref, so %{$self} evaluates to the object itself, rather than an instance variable.

    Other monks have also mentioned that your test code does not correctly produce a hash reference. See perlreftut and perldsc for more information.

Re: Trouble passing a hash to a module
by NetWallah (Canon) on Aug 27, 2019 at 22:48 UTC
    The main issue is - how perl interprets:
    %$self->{simple_hash}
    My attempt to explain the issue is likely to create more confusion, so I will leave that to others.

    What you could use in recent perls (>=5.20) is the postfix style :

    $self->%{simple_hash}

    Working code:

    use strict; use warnings; {package toy_module; sub new { my ($class, $args) = @_; my $self = { simple_hash => $args->{simple_hash}, simple_test_scalar => $args->{simple_test_scalar}, }; print "********** INSIDE SUBROUTINE NEW **********\n"; return bless $self, $class; } sub show_simple_hash { my $self = shift; print "********** INSIDE SUBROUTINE SHOW_SIMPLE_HASH ********* +*\n"; print "simple scalar: ".$self->{simple_test_scalar}."\n"; print "Simple Hash Key:$_\n" for keys %{$self->{simple_hash}}; } 1; } # End of package toy_module ########## MAIN ################### my $little_test_hashref = { COL_1 => 0, COL_2 => 1, COL_3 => 2, COL_4 => 3, COL_5 => 4, }; my $test_object = toy_module->new({simple_hash=>$little_test_hashref, +simple_test_scalar=>5}); $test_object->show_simple_hash;

                    "From there to here, from here to there, funny things are everywhere." -- Dr. Seuss

Re: [OT] Trouble passing a hash to a module
by AnomalousMonk (Archbishop) on Aug 27, 2019 at 22:15 UTC
    ... pass a hash as an argument to a module.

    Technically, what you are trying to do is pass a hash reference as an argument to a subroutine defined in a given package. (More precisely, since we're in OO-land now, to a method of a class.) It's possible to pass a hash or any other reference to a module when use-ing or require-ing it (see, e.g., constant), but that's another tale for another day. :)


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

Re: Trouble passing a hash to a module
by mcrepeau (Initiate) on Aug 28, 2019 at 00:11 UTC
    Thanks to all for the help. I suspected it had to do with the de-referencing, but the concept is fuzzy for me and I was going in circles trying to figure it out. I need to do some studying on that topic, clearly! Also sorry about the line numbers. I put them in because the stdout referred to specific line numbers, but I realize now that they are more of a nuisance than an aid in this context.
Re: [OT] Trouble passing a hash to a module
by AnomalousMonk (Archbishop) on Aug 27, 2019 at 21:38 UTC

    When you post code, please do not include line numbering; it makes cut/paste/running the code more difficult. Please see Short, Self-Contained, Correct Example. Please help us to help you. :)


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