Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I pass a hash to a function in Perl?

I have a function that takes a variable and an associative array, but I can't seem to get them to pass right. I think this has something to do with function declarations, however I can't figure out how they work in Perl. Is there a good reference for this and how do I accomplish what I need?

I should add that it needs to be passed by reference.

sub PrintAA {     my $test = shift;     my %aa   = shift;     print $test . "\n";     foreach (keys %aa)     {         print $_ . " : " . $aa{$_} . "\n";         $aa{$_} = $aa{$_} . "+";     } } 
like image 672
rlbond Avatar asked Apr 29 '09 19:04

rlbond


People also ask

How do I pass a hash function in Perl?

Show activity on this post. And if you do it that way and pass the hash as the last argument, you'll be fine without any tricks or special magic. E.g.: sub testFunc { my ( $string, %hash ) = @_; print "$string $hash{'abc'} $hash{'efg'} $string\n"; } my %testHash = ( 'abc' => "Hello,", 'efg' => "World!" ); testFunc('!!!

How do I reference a hash in Perl?

Similar to the array, Perl hash can also be referenced by placing the '\' character in front of the hash. The general form of referencing a hash is shown below. %author = ( 'name' => "Harsha", 'designation' => "Manager" ); $hash_ref = \%author; This can be de-referenced to access the values as shown below.

What does @_ do in Perl?

The @_ variable is an array that contains all the parameters passed into a subroutine. The parentheses around the $string variable are absolutely necessary. They designate that you are assigning variables from an array.

How can we access hash element in Perl?

Perl Hash Accessing To access single element of hash, ($) sign is used before the variable name. And then key element is written inside {} braces.


2 Answers

Pass the reference instead of the hash itself. As in

PrintAA("abc", \%fooHash);  sub PrintAA {   my $test = shift;   my $aaRef = shift;    print $test, "\n";   foreach (keys %{$aaRef})   {     print $_, " : ", $aaRef->{$_}, "\n";   } } 

See also perlfaq7: How can I pass/return a {Function, FileHandle, Array, Hash, Method, Regex}?

like image 60
Paul Tomblin Avatar answered Oct 05 '22 21:10

Paul Tomblin


This code works:

#!/bin/perl -w  use strict;  sub PrintAA {     my($test, %aa) = @_;     print $test . "\n";     foreach (keys %aa)     {         print $_ . " : " . $aa{$_} . "\n";     } }  my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA );  PrintAA("test", %hash); 

The key point is the use of the array context in the my() 'statement' in the function.


What does the array context business actually do?

Succinctly, it makes it work correctly.

It means that the first value in the @_ array of arguments is assigned to $test, and the remaining items are assigned to the hash %aa. Given the way I called it, there is an odd number of items in the @_, so once the first item is assigned to $test, there is an even number of items available to assign to %aa, with the first item of each pair being the key ('aaa', 'bbb', 'ccc' in my example), and the second being the corresponding value.

It would be possible to replace %aa with @aa, in which case, the array would have 6 items in it. It would also be possible to replace %aa with $aa, and in that case, the variable $aa would contain the value 'aaa', and the remaining values in @_ would be ignored by the assignment.

If you omit the parentheses around the variable list, Perl refuses to compile the code. One of the alternative answers showed the notation:

my $test = shift; my(%aa) = @_; 

This is pretty much equivalent to what I wrote; the difference is that after the two my statements, @_ only contains 6 elements in this variation, whereas in the single my version, it still contains 7 elements.

There are definitely other questions in SO about array context.


Actually, I wasn't asking about the my($test, %aa) = @_; I was asking about my(%hash) = ( 'aaa' => 1, 'bbb' => 'balls', 'ccc' => \&PrintAA ); versus my %hash = { 'aaa' => 1, ... };

The difference is that the { ... } notation generates a hash ref and the ( ... ) notation generates a list, which maps to a hash (as opposed to hash ref). Similarly, [ ... ] generates an array ref and not an array.

Indeed, change the 'main' code so it reads: my(%hash) = { ... }; and you get a run-time (but not compile time) error - treat line numbers with caution since I've added alternative codings to my file:

Reference found where even-sized list expected at xx.pl line 18. ... Use of uninitialized value in concatenation (.) or string at xx.pl line 13. 
like image 37
Jonathan Leffler Avatar answered Oct 05 '22 19:10

Jonathan Leffler