Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

Send hash of hash arguments to sub

by Dr Manhattan (Beadle)
on Aug 14, 2013 at 07:15 UTC ( #1049391=perlquestion: print w/replies, xml ) Need Help??
Dr Manhattan has asked for the wisdom of the Perl Monks concerning the following question:

Hi all

I have some data in a hash of hash. I want a function that receive any two strings in my data and return the value.

Here is a example of the data

did la 0.001 did bruja 0.001 did verde 0.001 not Maria 0.001 Mary Maria 0.8 Mary no 0.001 Mary dio 0.001 Mary una 0.001

And here is the code I am currently working on

sub probability { my (%hash, $source, $target) = @_; return $hash{$source}{$target}; } my $test = &probability(%hash, $hash{Mary}, $hash{Mary}{Maria}); print "$test\n";

I expect the output to be 0.8

Thanks in advance for any help

Replies are listed 'Best First'.
Re: Send hash of hash arguments to sub
by kcott (Chancellor) on Aug 14, 2013 at 07:47 UTC

    G'day Dr Manhattan,

    You have a number of problems here.

    When you call probability(), @_ contains all the keys and values from %hash, the hashref $hash{Mary}, and the value 0.8 from $hash{Mary}{Maria} (which is actually the value you want returned, so calling a subroutine is pointless in this instance).

    When assigning those values to (%hash, $source, $target), they are all assigned to %hash leaving $source and $target undefined.

    You're calling probability() with a leading ampersand (&). This probably isn't what you want and may (in the context of your real progam) be doing something unexpected. Don't add leading ampersands to your subroutine calls unless that's really what you want and you understand the implications of what you are doing! See perlsub for a more detailed discussion.

    The code I suspect you want is probably closer to this:

    $ perl -Mstrict -Mwarnings -e ' my %hash = (Mary => { Maria => 0.8}, other_keys => "other_values") +; sub probability { my ($hash_ref, $source, $target) = @_; return $hash_ref->{$source}{$target}; } my $test = probability(\%hash, "Mary", "Maria"); print "$test\n"; ' 0.8

    -- Ken

      Another possibility is:

      my %hash = (Mary => { Maria => 0.8}, other_keys => "other_values"); sub probability (\%$$) { my ($hash_ref, $source, $target) = @_; return $hash_ref->{$source}{$target}; } my $test = probability(%hash, "Mary", "Maria"); print "$test\n";
      package Cow { use Moo; has name => (is => 'lazy', default => sub { 'Mooington' }) } say Cow->new->name
Re: Send hash of hash arguments to sub
by Laurent_R (Canon) on Aug 14, 2013 at 08:26 UTC

    As it has already been said, it seems pointless to use a subroutine in such a case. However, assuming you want to fix your code and understand what's going on, you would need to pass a hash ref, rather than the hash itself, as explained by others above, including kcott. Or another fix would be to put your hash as the last element of your argument list:

    sub probability { my ($source, $target, %hash) = @_; return $hash{$source}{$target}; } my $proba = probability($key_level1, $key_level2, %hash);

    This way, the hash does not "eat" the trailing arguments.

    Update: Corrected a copy_and_paste error and the missing name of the subroutine in the function call. I had to go, I was too hasty on typing this.

      You are not passing a hash ref. and neither do you have the variable $hash_ref defined. Then the subroutine is not called anywhere.

Re: Send hash of hash arguments to sub (Dumper reference my %hash = @_ )
by Anonymous Monk on Aug 14, 2013 at 07:28 UTC

    Can't be done, you can only send references

    Basic debugging checklist item 4 ( Dumper )

    my( %hashgetsthemall, $two, $eleven ) = 1 .. 11; dd \%hashgetsthemall, $two, $eleven ; __END__ ( { 1 => 2, 3 => 4, 5 => 6, 7 => 8, 9 => 10, 11 => undef }, undef, undef, )

      my( %hashgetsthemall, $two, $eleven ) = 1 .. 11;

      my( $one, $two, %hashgetstherest ) = 1 .. 12;

      is one way to do it if you wanted copies of the values anyway.
      The list variable must come last though, and there can be only one.


        In the OP's example that is:

        my ($source, $target, %hash) = @_;

        Cheers, Sören

      Créateur des bugs mobiles - let loose once, run everywhere.
      (hooked on the Perl Programming language)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1049391]
Approved by kcott
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (8)
As of 2018-05-23 15:55 GMT
Find Nodes?
    Voting Booth?