in reply to Transferring local hashes to module subroutines

Some background:
%var - Hash $var{$key} - Hash element $var - Scalar. No relation to %var

Excerpt from your code:

return &Y::module_subroutine($hash_to_send); sub module_subroutine { my($hash) = @_; return "The colour of the sky is ". $hash{third_colour}; }

Fix 1:

return &Y::module_subroutine(%hash_to_send); <--- Use the right var sub module_subroutine { my(%hash) = @_; <--- Use the right type return "The colour of the sky is ". $hash{third_colour}; }

The above copies the entire hash (%hash = %hash_to_send;). To avoid that cost, a reference is usually passed. Fix 2:

return &Y::module_subroutine(\%hash_to_send); <--- Pass reference sub module_subroutine { my($hash) = @_; <--- A ref to a hash return "The colour of the sky is ". $hash->{third_colour}; <--- Must dereference }

Replies are listed 'Best First'.
Re^2: Transferring local hashes to module subroutines
by cowgirl (Acolyte) on Aug 06, 2008 at 14:27 UTC
    Thanks for the great replies. It's working well now. Is it possible though to send an extra scalar as parameter to the subroutine? I have not been able to get this working.
    sub module_subroutine { my (%hash,$scalar) = @_; return "The color of the ".$scalar." is ".$hash{color}; } my %hash_to_send; my $scalar = "water"; $hash_to_send{color} = "red"; print module_subroutine(%hash_to_send,$scalar);
    I am using strict now as suggested and it tells me there is an odd number of elements in the hash assignment at my (%hash,$scalar) = @_;. What is going on here?
      Understand that, as far as perl is concerned, passing an array or a hash is the same as passing a list of values. This is known as list context.
      # functionally speaking, this.... %hash = ('a' => 1, 'b' => 2, 'c' => 3); myfunc(%hash); # is the same as this... myfunc('a', 1, 'b', 2, 'c', 3);
      So you'll either want to put the scalar value first and shift it off:
      $scalar = 'blue'; %hash = ('a' => 1, 'b' => 2); myfunc($scalar, %hash); sub myfunc { my $scalar = shift; my %hash = @_; print $hash{'a'}; }
      Or pass arrays and hashes by reference, because when you pass a reference to an array or hash, the reference is a scalar context.
      %hash = ('a' => 1, 'b' => 2); $scalar = 'blue'; myfunc(\%hash, $scalar); sub myfunc { my($hashref,$scalar) = @_; print $hashref->{'a'}; }

      __________
      Systems development is like banging your head against a wall...
      It's usually very painful, but if you're persistent, you'll get through it.

      All functions accept only one thing as arguments: a list of scalar.

      When you do func(%hash), the hash gets flatten into a list. For example

      sub show_args { print(join(', ', @_), "\n"); } my %hash = ( a=>1, b=>2, c=>3 ); show_args(%hash); # c, 3, a, 1, b, 2

      Same goes if you also pass some scalars.

      my %hash = ( a=>1, b=>2, c=>3 ); show_args(%hash, "d", 4); # c, 3, a, 1, b, 2, d, 4

      So when you assign @_ to a hash (or an array), the hash absorbs the entire list. Perl has no way to know that only part of the assigned list should end up in the hash unless you tell it to.

      Passing a reference to the hash avoids this issue too.

      The problem is in the line my (%hash,$scalar) = @_ This is not going to work ("passing both in one go"). See Passing hash and hashref to sub for a recent discussion on the topic. As usual there are more solutions to the problem. I would advice to use a hashref.