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

I have a package which has functions with hashref prototypes. An illustrative example:
sub foo(\%) { my $h = shift; # do something with it... $h->{"FOO"} = "Hello, world!"; }
Well, when I use the package and call those functions, they won't work with stuff like the following (Perl nags that I must use a hash and not a hash reference):
my %stash; foo(\%stash);
But calling it with foo(%stash) works. Why is that? The prototype says to expect a hash reference after all. I tried eyeballing through the Perl Cookbook, Learning Perl, Programming Perl and even Advanced Perl Programming but found no help. I have use strict pragma turned on. Am I missing something subtle here? I wish my function prototypes were consistent... Anyone?

Replies are listed 'Best First'.
RE: Hash reference question
by davorg (Chancellor) on Jul 13, 2000 at 16:22 UTC

    From perldoc perlsub (in the section on Prototypes):

    Any backslashed prototype character represents an actual 
    argument that absolutely must start with that character.
    The value passed to the subroutine (as part of @_) will be 
    a reference to the actual argument given in the subroutine 
    call, obtained by applying \ to that argument. 
    

    I interepret that to mean that the behaviour that you're seeing in correct. Perl expects you to pass a hash to the subroutine. Perl will then take a reference to the hash and pass that into the subroutine as the argument. You should therefore pass a hash into the subroutine, but expect a reference to a hash within the subroutine.

    --
    <http://www.dave.org.uk>

    European Perl Conference - Sept 22/24 2000, ICA, London
    <http://www.yapc.org/Europe/>
      davorg is, of course, correct.

      I just wanted to add my generic advice that you shouldn't use prototypes unless you get in a position where you need them. I made the same mistake as you early on, finding function prototypes in perldoc, and thinking I should use them everywhere. I have since revisited my old code and removed all the prototypes.

      They're indispensable when you need them, and a real irritant when you don't. If you don't know when you need them, then you don't need them.

      *Woof*

      Thanks! That was it. I assumed that I must tell Perl that it's a hash reference, using eg. foo(\%someHash); Indeed, it seems that Perl takes a reference from the given hash behind the scenes so to speak. Good to know though, now I can finish the documentation :)
Re: Hash reference question
by Abigail (Deacon) on Jul 13, 2000 at 22:27 UTC
    Usually, when you want a hashreference, you use the $ prototype. After all, a hash reference is a scalar. The prototypes \% and \@ are special. It means that a variable in that slot has to start with a % or a @, and that the hash or array will not be flattened out. You would use this to prototype functions with a similar behaviour as keys or push.

    -- Abigail

      The funny thing about the issue is that this worked OK:
      my %funny; foo(\%funny); sub foo(\%) { my $foo = shift; $foo->{"FOO"} = "BAR"; }
      If foo was from a module, it didn't work.. But thanks, now I know.
Re: Hash reference question
by c-era (Curate) on Jul 13, 2000 at 15:13 UTC
    If you print out $h you will see that it displays something like "HASH(0x123a)", but if you print %$h your hash will print out. You can access keys by $$h{key}.

    If all you are passing is the hash you do not need to use a refrence. Just leave your code the way it is and pass the hash. If you are passing more then the hash to the array it is best if you use refrences. Just change all $h to $$h and all %h to %$h.

I forgot something
by Anonymous Monk on Jul 13, 2000 at 15:12 UTC
    Perl version is 5.004_04 with "1 registered patch".. is this the problem?