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

Hello, How do you:
1. pass a hash to a subroutine
2. send it as a reference to a subroutine so it changes the original variable

use strict; use warnings; my %list=("bob" =>123, "tom" => "CAT"); #Assign values change (%list); sub change{ my %A = shift @_; #Get Values foreach (keys %A){ print "$_ = $A{$_}\n"; \$A{$_} .= "hello"; #Change Values } } foreach (keys %list){ print "$_ = $list{$_}";#Print New Values }

This code doesnt work.

"Odd number of elements in hash assignment at C:\Documents and Setting +s\Jason\My Documents\perltest\Perl-1.pl line 8."
Thanks

Replies are listed 'Best First'.
Re: referances of hashes, and subroutines
by japhy (Canon) on Apr 22, 2006 at 19:39 UTC
    Check perlreftut; your primary mistakes are:
    1. Not sending %list by reference: change(\%list);
    2. shift()ing @_ and expecting an aggregate back; instead, use: my $href = shift @_;
    Once you have $href, you use %$href wherever you used %A.
    foreach (keys %$href) { print "$_ = $href->{$_}\n"; # or $$href{$_} ... }

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart
Re: referances of hashes, and subroutines
by GrandFather (Saint) on Apr 22, 2006 at 19:52 UTC

    First off, ++ for asking the question nicely and for including use strict; use warnings; in your code. Not so good however is that there is a syntax error in the code that you posted. \$A{$_} .= "hello"; #Change Values is broken syntax and should have generated an error when you tied to run the code. Mentioning the error would leave less egg on your face!

    That aside, you have vaugely the right idea, you just haven't found the right way to apply it. Try this instead:

    use strict; use warnings; my %hash=("bob" =>123, "tom" => "CAT"); #Assign values change (\%hash); #Print New Values print "$_ = $hash{$_}\n" foreach keys %hash; sub change{ my $hashRef = shift; #Get the reference to the values foreach (keys %$hashRef){ print "$_ = $hashRef->{$_}\n"; $hashRef->{$_} .= "hello"; #Change Values } }

    Prints:

    tom = CAT bob = 123 tom = CAThello bob = 123hello

    Note in particular that a reference to the hash is passed to the sub and that the reference has to be dereferenced with -> to access the hash.


    DWIM is Perl's answer to Gödel
Re: referances of hashes, and subroutines
by zer (Deacon) on Apr 22, 2006 at 19:38 UTC
    that error is because you didnt pass the variable correctly. The shift will take the first element off of an array so...
    sub change{ my %A = @_;
Re: referances of hashes, and subroutines
by tempest (Sexton) on Apr 22, 2006 at 20:00 UTC
    how can i make this more like pop() or shift() where you dont send the reference to the subroutine, it just changes it?

      shift and pop are part of the language and are more like operators than subroutines. They can therefore do magic that is not available to mere mortals.

      Others will very likely show ways of doing what you would like using deep Perl magic. But in most cases doing such stuff is likely to cause grief in the long run as your eye becomes accoustomed to Perl and gets confused by special magic.

      The simple rule is that Perl passes by value. If you want a reference to something then you have to do that explicitely. Confounding that rule (by invoking special magic) will, in the long run, cause trouble because the reader of the code must check every subroutine to see if it might alter parameters in unexpected ways.


      DWIM is Perl's answer to Gödel
        it isnt as much magical as it is prototyping.
        use strict; use warnings; my %list=("bob" =>123, "tom" => "CAT"); sub change(\%){ my $temp = shift; foreach (keys %$temp){ print $_. " = $$temp{$_}\n"; $$temp{$_} .= "hello"; } } change (%list); foreach (keys %list){ print "$_ = $list{$_}\n"; }
        declaring the subroutine as sub change(\%){ will send the values as a reference
      When you want sm.th. like pop() and shift() you use pop() and shift() without reinventing the wheel.


        ya im not reinventing the weel. As you can see in the example. Im just trying to learn the ins and outs of the language