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

A simple question. It has been a long time since I programmed in perl, and for some reason I can't seem to sort this problem out. References in perl....

#!/usr/local/bin/perl -w use strict; sub get_conf(\%); my %cur_conf; $cur_conf{test} = "test"; get_conf(\%cur_conf); print "after: " . $cur_conf{test}; sub get_conf(\%) { my $href = @_; $href->{test} = "another test"; }

To my tired newbie eyes, this looks like it should work but does not. Thanks for any help.

gnubbs

Replies are listed 'Best First'.
Re: Hashes and Functions
by jasonk (Parson) on Apr 10, 2003 at 18:00 UTC
    my $href = @_;

    Evaluating an array as a scalar returns the number of elements in the array, so at this point $href contains '1'. You want either my($href) = @_; or my $href = shift;, or something similar that will maintain the array context you are looking for.


    We're not surrounded, we're in a target-rich environment!

      Thanks! This was something that took me a while to get right when I was first learning perl, and now I see why. In the camel book the line is:

      my ($cref, $dref) = @_;

      For some reason, I had associated the () with the my... Now it makes perfect sense. Thanks.

      gnubbs

        Actually, in that case the parens are associated with my. You can think of my as a function just like any other function and the parens group and specify its arguments. The reason you can assign to it is because my returns a list of its newly scoped arguments, which are then assigned to like any other list assignment.

        kelan


        Perl6 Grammar Student

        IMHO, "shift" is the better way to get arguments off of @_. If you start using "shift", you'll never get confused about scalar vs. list context, etc.

        So,

        my ($cref, $dref) = @_;

        becomes

        my $cref = shift; my $dref = shift;

        Very clean, very easy. No confusion :-)

        HTH.

Re: Hashes and Functions
by bart (Canon) on Apr 11, 2003 at 00:56 UTC
    You have two problems. One has been addressed in other replies, on your way to pass the parameter to the local, lexical variable.

    But a second problem is that prototypes change the way you have to call your sub. With a prototype \%, perl wants you to pass in a hash, and it will pass on a reference to it to the sub. So the call should look like:

    get_conf(%cur_conf);
    With that additional change, your code runs as expected, on my system (perl 5.6.1).

    Similar, with a prototype \@, you must pass in an array, not an array reference:

    sub mypush (\@@) { my $aref = shift; push @$aref, @_; } @a = (1); mypush @a, 2, 3, 4; print "@a\n";
    Resulting in: 1 2 3 4