Frage

I am working with passing hashes to various subroutines, and I was wondering how to pass a hash to a subroutine and then pass the same hash inside that subroutine to a different subroutine and so on.

For example, the following code works fine.

use strict;
use warnings;

my %hash = ( 
    key1 => 'value1',
    key2 => 'value2',
    key3 => 'value3',
    key4 => '', 
);      

print %hash, "\n"; 
check_it(\%hash);

sub check_it {
    my $params = shift; 

    foreach(keys %{$params}){        
        if($params->{$_}) {
            print "'$_' defined as '$params->{$_}'\n";
        }   
        else {
            print "'$_' not defined as '$params->{$_}'. Deleting it.\n"; 
            #delete $params->{$_};
            $params->{$_} = 'null';
        }     
    } 

    for ( my $i = 0 ; $i < 7 ; $i++ ) {
        print "looping\n";
        &check_tags_again(\%hash);
    }     
}   

sub check_tags_again {
    my $hash_now = shift;

    #check again...
    foreach(keys %{$hash_now}){
        print "An element of hash: ", $hash_now->{$_}, "\n";
        #if(defined $hash_now->{$_}){ delete $hash_now->{$_};}
    }
    &check_tags_thrice(\%hash);
}   

sub check_tags_thrice {
    my $hash_now = shift;

    #check again...
    foreach(keys %{$hash_now}){
        print "An element of hash: ", $hash_now->{$_}, "\n";
        #if(defined $hash_now->{$_}){ delete $hash_now->{$_};}
    }   
}   

print "final hash:", %hash, "\n";

BUT, when I run the code that follows:

use strict;
use warnings;
use Data::Dumper;

sub process_data {

    my $group_size = 10; 

    my %HoA = ( 
        flintstones => [ "fred",   "barney" ],
        jetsons     => [ "george", "jane", "elroy" ],
        simpsons    => [ "homer",  "marge", "bart" ],
    );      

    &delete_stuff( \%HoA, $group_size );
    print "New group:\n";
    print Dumper( \%HoA );
    undef %HoA;
}   

sub delete_stuff {
    my $HoARef     = shift;
    my $group_size = shift;

    print "group size in sub $group_size\n";

    for ( my $j = 0 ; $j < $group_size ; $j++ ) { 
        my $dlted = &delete_other_stuff( \%HoA, $j );
        print "deleted? '$dlted'\n";

        if ( $dlted == 0 ) { 
            &presence_check( \%HoA, $j );
        }   

        for ( my $i = 0 ; $i < $group_size ; $i++ ) { 
        }   
    }   
}   

sub delete_other_stuff {
    my $HoAref  = shift;
    my $Dex     = shift;
    return $deleted;
}   

sub presence_check {
    my $HoAreF = shift;
    my $DeX    = shift;
}

I get:

 Global symbol "%HoA" requires explicit package name at x.pl line 32.
 Global symbol "%HoA" requires explicit package name at x.pl line 35.
 Execution of x.pl aborted due to compilation errors.

I'm confused because I think it's doing the same thing as the first, but now it claims that %HoA was never initialized.

War es hilfreich?

Lösung

In delete_stuff, you don't have %HoA, you have $HoARef. If all the subs are expecting a reference to a hash, then you can just use it:

for ( my $j = 0 ; $j < $group_size ; $j++ ) { 
    my $dlted = &delete_other_stuff( $HoARef, $j );
    print "deleted? '$dlted'\n";

    if ( $dlted == 0 ) { 
        &presence_check( $HoARef, $j );
    }
    ...
}

By the way, we're closing on 20 years of Perl 5. There is no reason to call a sub with explicitly passed parameters with an &, which is a Perl 4 holdover.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top