Search code examples
perlreference

Perl subroutine in package to modify hash outside of it


to summarize:

  • i have a main script with a hash in it
  • this main script calls a package, where i have a subroutine from where i want to modify the contents of this global hash (to add elements to it)

this is an extremely simplified extraction of my code i have put in /tmp to illustrate my issue :

main script (/tmp/nonstdtest.pl) :

#!/usr/bin/perl

use lib '/tmp';

use TEST;
use Data::Dumper;

my %nonstd;

tNumber(\%nonstd);

print Dumper(\%nonstd);

the package (/tmp/TEST.pm) :

package TEST;

use strict;
use warnings;

use Exporter;

our @ISA= qw( Exporter );
our @EXPORT_OK = qw( tNumber );
our @EXPORT = qw( tNumber );

sub tNumber {

   my $nonstd      = shift;
   $nonstd      = %$nonstd;

   $nonstd{'example'} = 'test_here';

}

problem, the output is :

Global symbol "%nonstd" requires explicit package name at /tmp/TEST.pm line 15.
Compilation failed in require at /tmp/nonstdtest.pl line 5.
BEGIN failed--compilation aborted at /tmp/nonstdtest.pl line 5.

question : how can i modify the contents of %nonstd (defined in the main script) with my subroutine defined within the package ?

i have tried to do it without a package (within the same script), and it runs OK (as long as i keep the hash with the same name in the subroutine) so i'm doing something wrong here.

the result i would expect in the example above is simply to have %nonstd filled with 1 key/value pair (example/test_here)


Solution

  • Your problem is a typo:

    $nonstd{'example'} = 'test_here';
    

    Is trying to get a key from %nonstd, but you declared my $nonstd, which is a scalar. They are not the same variable. And it violates the strict pragma, which is why we use strict, because it helps us catch typos.

    It should be:

    $nonstd->{'example'} = 'test_here';
    

    Using the arrow operator -> for a hash reference. But then this is also wrong:

    $nonstd      = %$nonstd;
    

    You already had the hash reference, but now you replaced it with the size of the hash, which is what you get when you put a hash in scalar context. So in effect, you have destroyed the hash reference. Just delete this line.

    Afterwards, it works as expected and prints out:

    $VAR1 = {
              'example' => 'test_here'
            };