3
my %hash = ('red' => "John", 'blue' => "Smith"); 
func (%hash);  

sub func {
    my $hash = $_[0];
    print "$hash{'red'}\n";
    print "$hash{'blue'}\n";
}

I send a hash to a subroutine, and this hash is treated as scalar. If so, how is it possible that I can turn to a value in the hash by calling its key?

user3189985
  • 189
  • 5
  • 14

3 Answers3

12
func(%hash);

is equivalent to

func('red', 'John', 'blue', 'Smith'); 
   -or-
func('blue', 'Smith', 'red', 'John'); 

so

my $hash = $_[0];

is equivalent to

my $hash = 'red';
   -or-
my $hash = 'blue';

Totally useless. Good thing you never use $hash ever again.


Instead, you use the %hash declared outside the sub. You can see this by reordering your code or by limiting the scope (visibility) of %hash.

use strict;
use warnings;

{
    my %hash = ('red' => "John", 'blue' => "Smith"); 
    func(%hash);  
}

sub func {
    my $hash = $_[0];
    print "$hash{'red'}\n";
    print "$hash{'blue'}\n";
}

$ perl a.pl
Global symbol "%hash" requires explicit package name at a.pl line 11.
Global symbol "%hash" requires explicit package name at a.pl line 12.
Execution of a.pl aborted due to compilation errors.

The solution is to pass a reference.

use strict;
use warnings;

{
    my %hash = ('red' => "John", 'blue' => "Smith"); 
    func(\%hash);
}

sub func {
    my $hash = $_[0];
    print "$hash->{'red'}\n";
    print "$hash->{'blue'}\n";
}
ikegami
  • 367,544
  • 15
  • 269
  • 518
2

Because the scope of your %hash is the entire program.

Konerak
  • 39,272
  • 12
  • 98
  • 118
0

%hash is supposed to be local. no?

It's local to the enclosing scope. Scopes are delimited by braces. But there are no braces anywhere surrounding your declaration:

my %hash;

As a result, %hash is visible inside every nested scope in the file. Here is an example:

use strict;
use warnings;
use 5.016;

my $str = "hello";

if (1) { #new scope starts here
    say "if: $str";
} #scope ends here

{ #new scope starts here

    my $planet = "world";
    say "block: $str";

    for (1..2) { #new scope starts here
        say "for: $str $planet";
    } #scope ends here

} #scope ends here

#say $planet;  #The $planet that was previously declared isn't visible here, so this looks
               #like  you are trying to print a global variable, which results in a
               #compile error, because global variables are illegal with: use strict;


--output:--
if: hello
block: hello
for: hello world
for: hello world
7stud
  • 46,922
  • 14
  • 101
  • 127