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

This will probably be so easy I will kick myself over the entire weekend, but here goes.

I have a sub routine which returns a HASH reference to a data structure as follows

$myhash{$key}->($value1, $value2)
In the calling program I can dereference the hash no problem.
foreach $key (%$ref){ ($value1, $value2)= @$ref{$key} ##do something... }
However when I pass the same $ref to a sub routine
mysub($ref); sub mysub{ my $param = (@_); foreach $key (%$param){ ($value1, $value2)= @$param{$key} ##do something... } }
Does not work. Where am I going wrong? Thanks.

Updated for Tomte, yes it was a typo in the posting sorry!

Replies are listed 'Best First'.
Re: A dereferencing problem
by gnork (Scribe) on Apr 29, 2004 at 09:41 UTC
    Hi!

    Take a closer look at that line:
    foreach $key (%$ref){
    This is the first error/bug to correct. I'd suggest, you read "perldoc -f keys".

    Rgds
    Gnork

    cat /dev/world | perl -e "(/(^.*? \?) 42\!/) && (print $1))"
    errors->(c)
Re: A dereferencing problem
by dave_the_m (Monsignor) on Apr 29, 2004 at 12:11 UTC
    Your problem lies here:
    my $param = (@_);
    You evaluate @_ in scalar context, which returns the number of elements (1). You need this instead:
    my ($param)= @_;
Re: A dereferencing problem
by Tomte (Priest) on Apr 29, 2004 at 09:24 UTC

    Do you use strict; use warnings;?

    You dereference $ref in the foreach-loop, while you certainly meant to dereference $param.

    Or is this a typo that occured while posting the code?

    regards,
    tomte


    An intellectual is someone whose mind watches itself.
    -- Albert Camus

      Yes I was using strict and got something about can't use 1 as referance while using strict.

        And is $ref a typo or your actual code?

        Try gnorks advice, and let the offending line look like

        foreach my $key (keys(%$param)) {
        Or try to be more specific in your questions, always mentioning
        what
        code stripped down to a minimum
        where
        in the code
        which results
        e.g. error messages you got
        why
        Problem you try to solve
        (not necessarily in this order and on occasion deeply nested :)

        Edit: fixed $% to %$

        regards,
        tomte


        An intellectual is someone whose mind watches itself.
        -- Albert Camus

Re: A dereferencing problem
by periapt (Hermit) on Apr 29, 2004 at 13:38 UTC
    I couldn't quite get your code working the way you describe it. I may be missing some point in your program's process. However, assuming your data structure is a hash of arrays (HoA) and you are trying to recover the values from the arrays. Here is what I came up with.
    # Compiler directives and Includes use strict; use warnings; use diagnostics; # Global declarations; # Constants and pragmas use constant TRUE => scalar 1; use constant FALSE => scalar 0; ###########################################################; #main() { my $value1 = 0; my $value2 = 0; my $ref = RtnRef(); my $key = ''; # this line will rtn both the key and the value from the hash # foreach $key (%$ref){ foreach $key (keys %$ref){ # this works # ($value1, $value2)= @$ref{$key} # @$ref{$key} rtns array ref ($value1, $value2)= @{$ref->{$key}} # rtns array vals ##do something... } #However when I pass the same $ref to a sub routine mysub($ref); exit; } #end main() ############################################################; sub mysub{ # my $param = (@_); # this rtns scalar @_ (== 1)) # my ($param) = (@_); # this works ($param = $ref) my $param = shift; # and so does this my $key = ''; my $value1 = 0; my $value2 = 0; # foreach $key (%$param){ foreach $key (keys %$param){ # ($value1, $value2)= @$param{$key} ($value1, $value2)= @{$param->{$key}} ##do something... } return; } ###########################################################; sub RtnRef{ my %myhash = (); my $key = 'key1'; $myhash{'key1'} = [23, 40]; $myhash{'key2'} = [01, 50]; $myhash{'key3'} = [99, 22]; return \%myhash; } ############################################################;
Re: A dereferencing problem
by revdiablo (Prior) on Apr 29, 2004 at 16:53 UTC

    It appears you have already been sufficiently answered, but I have a quick nitpicky comment that will probably get me some giggle-inducing downvotes. In your question, you say:

    I have a sub routine which returns a HASH reference to a data structure as follows

    $myhash{$key}->($value1, $value2)

    I'm not sure if you meant that %myhash contains an array reference at $key, but your code seems to indicate that it's actually a code reference. The syntax you have is exactly that for calling a code reference, and passing $value1 and $value2 as arguments to it.

      It does sort of look that way, doesn't it? I think the code suggests the HoA structure though. If he were using code references, the assignment line would be more like  ($value1, $value2)= &{$ref->{$key}} with the assumption that the referenced function returned a list. If the referenced function returned a pointer to an array then the assignment would be  ($value1, $value2)= @{&{$ref->{$key}}} which is getting decidedly unlovely in appearance.

      PJ
        It does sort of look that way, doesn't it?

        No, it doesn't look that way, it is that way. I was pretty sure he meant that there was an array reference at that key, but trying to point out that the actual syntax of his "example" was something completely different (that is, calling a coderef stored in the hash).

        Incidentally, your two examples can be written as ($value1, $value2) = $ref->{$key}->() and ($value1, $value2) = @{ $ref->{$key}->() }, which I find more readable.