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

Why doesn't this work as I expect?
my %h = (a,b,c,d); &func(\%h); while ((my $key, my $val) = each %h) { print "key is $key val is $val\n"; } sub func { $_->{'e'} = 'f'; }

The output is
key is c val is d key is a val is b
but I also want it to print out
key is e val is f

How can I get it to produce what I want?

Replies are listed 'Best First'.
Re: directly modify hash from subroutine
by stevieb (Canon) on Sep 04, 2009 at 23:47 UTC
    #!/usr/bin/perl use strict; use warnings; my %h = qw( a b c d ); func( \%h ); while ( my ( $key, $val ) = each %h ) { print "key is $key val is $val\n"; } sub func { my $incoming_hash_ref = shift; $incoming_hash_ref->{'e'} = 'f'; }

    prints:

    key is e val is f key is c val is d key is a val is b

    IOW, the $_ isn't doing what you think it is doing (AFAICT).

    Steve

Re: directly modify hash from subroutine
by marksman (Novice) on Sep 05, 2009 at 00:04 UTC
    Ok, yeah if I replace $_ with $_[0] then it works.
    I guess I didn't understand the way function parameters were passed. So the arguments are always in @_, not $_, is that correct?

      That is (almost always) correct. There's a special case related to subroutine prototypes in Perl 5.10, but you can safely and successfully ignore that for a very, very long time.

      Great, well you know that @_ would hold the arguments passed to a subroutine and you correlated that with array element indexing. Function (subroutines) parameters are passed either directly or by reference, but you have to remember:
      • using & to call a subroutine would disable prototype checking on the arguments if you have specified a subroutine that accepts certain types of arguments.
      • modifying a reference inside a subroutine would modify the original data as is the case with references modification in general.


      Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.