Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Passing hashes as arguments to a sub?

by Spidy (Chaplain)
on Nov 28, 2005 at 17:44 UTC ( #512300=perlquestion: print w/ replies, xml ) Need Help??
Spidy has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash(%arguments), which has all of the arguments passed to my script. I have a function that is supposed to take this hash, check for certain keys, and then do things based on it. How would I go about passing the hash to my function? I've used
my ($varOne,$varTwo) = @_;
For passing multiple arguments as scalars/arrays...but I don't think that would work with a hash. Anyone know how I'd do it?


Comment on Passing hashes as arguments to a sub?
Download Code
Replies are listed 'Best First'.
Re: Passing hashes as arguments to a sub?
by ikegami (Pope) on Nov 28, 2005 at 17:54 UTC

    Only scalars can be passed as arguments, so either need to pass a reference (like in the first and second snippet), or flatten the hash into a list of scalars (like in the third snippet).

    One usually passes a reference to the hash which saves Perl from copying the entire hash:

    sub function { my ($hash_ref) = @_; foreach (keys %$hash_ref) { ... } } function(\%hash);
    If you don't with to work with references, you could use an alias:
    sub function { our %hash; local *hash = \$_[0]; foreach (keys %hash) { ... } } function(\%hash);
    Or you could create a copy of the hash if it's the last argument:
    sub function { my %hash = @_; foreach (keys %hash) { ... } } function(%hash);
Re: Passing hashes as arguments to a sub?
by wfsp (Abbot) on Nov 28, 2005 at 17:50 UTC

    Would this do it?

    my %hash = @_;

    #!/bin/perl5 use strict; use warnings; my %hash = ( one => 1, two => 2, ); my_sub(%hash); sub my_sub{ my %hash = @_; for my $key (keys %hash){ print "$key -> $hash{$key}\n"; } }

    update: added snippet


Re: Passing hashes as arguments to a sub?
by rinceWind (Monsignor) on Nov 28, 2005 at 18:00 UTC

    As wfsp has said, you can just assign @_ and this will treat the passed list of parameters as a set of key and value pairs. Note that an odd number of params will result in a run time exception.

    But, you often want to perform some (often elementary) validation on the input parameters, before casting them to a hash, such as checking that the keys are what you expect. Params::Validate is what I tend to use to do this, though there are other CPAN modules which do similar things. There are plenty of examples of how to use it in the docs.


    Oh Lord, wonít you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, wonít you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

Re: Passing hashes as arguments to a sub?
by jimbojones (Friar) on Nov 28, 2005 at 21:30 UTC
    TheDamian's new book, Perl Best Practices, covers this in Chapter 9. He recommends passing a hash reference, typically to an anonymous hash.

    my $foo = CalcFoo( { bar => 'abc', baz => 'def' } ); sub CalcFoo { my $href = $_[0]; my $foo; if ( defined $href->{bar} and defined $href->{baz} ) { $foo = $href->{bar} . $href->{baz}; } else { print "Error: pls define bar and baz\n"; } return $foo; }
    The reasons given for not passing a list of raw key/value pairs is:
    Requiring the named arguments to be specified inside a hash ensures that any mismatch, such as:
    $line = padded({text=>$line, cols=>20..21, centered=>1, filler=>$SPACE +});
    will be reported (usually at compile time) in the callerís context:
    Odd number of elements in anonymous hash at line 42
    Passing those arguments as raw pairs:
    $line = padded(text=>$line, cols=>20..21, centered=>1, filler=>$SPACE) +;
    would cause the exception to be thrown at run time, and from the line inside the subroutine where the odd number of arguments were unpacked and assigned to a hash:
    The chapter on subroutines is currently available as a sample chapter on the O'Reilly website for you to peruse. It's a great book, highly recommended.

    - j

Re: Passing hashes as arguments to a sub?
by eff_i_g (Curate) on Nov 28, 2005 at 18:11 UTC
    I'm not familiar with Params::Validate that was mentioned; however, there is a simple example of being strict with hash keys in "Perl Medic." It goes something like this:
    sub name { # this puts the passed list into a hash my %arg = @_; # this transfers values to variables and removes the keys my ($key1, $key2) = delete @arg{qw(key1 key2)}; # this determines if any keys are leftover croak 'Illegal arguments' if %arg; }
      #make hash my %junk = ( one=>'123123', two=>'dsf4f3' ) # send reference &printvals(\%junk); sub printvals { my $junk=$_[0]; #dereference these guys print $$junk{one} . $$junk{two}; }

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://512300]
Approved by NetWallah
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (6)
As of 2015-11-30 23:24 GMT
Find Nodes?
    Voting Booth?

    What would be the most significant thing to happen if a rope (or wire) tied the Earth and the Moon together?

    Results (788 votes), past polls