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

Assuming %URLS is a hash of lists, when I try to print out the elements in this hash with a subroutine it doesn't work.
%URLS = (); .. #code # add elements to hash .. .. sub printurls() { my (%URLS,$title) = @_; ... #code # print hash elements.... ... }
however, if I switch the arguments, the code works
sub printurls() { my ($title,%URLS) = @_; ... #code # print hash elements.... ... }
I was curious why this happened.
thanks.

Replies are listed 'Best First'.
Re: Hash of Lists Subroutine Problem
by jasonk (Parson) on Feb 23, 2003 at 22:42 UTC

    When you pass a hash, it is passed as a list, so everything you are passing to the subroutine is ending up in %URLS, leaving $title empty (and perl would warn you of this, by telling you that an odd number of elements had been assigned to a hash, if you were using -w). To avoid the problem you either have to pass scalars first, and put the list at the end, or pass lists by reference.

    To pass by reference you can either do it explicitly:

    printurls(\%URLS,$title); sub printurls { my($urls,$title) = @_; my %URLS = %{$url}; }

    Or, you can use prototypes, to make them references for you:

    printurls(%URLS,$title); sub printurls(%$) { my($urls,$title) = @_; my %URLS = %{$urls}; }
Re: Hash of Lists Subroutine Problem
by grantm (Parson) on Feb 23, 2003 at 21:59 UTC

    When your subroutine is called, it is passed a list of values: key1, value1, ... keyn, valuen, title. One way to avoid this problem is to pass a reference to the hash instead of the contents of the hash:

    printurls(\%URLS, $title); ... my ($URLS, $title) = @_; ... while(my($key, $value) = each %$URLS) { print "$key => $value\n"; }

    You can also use subroutine prototypes to transparently pass a hashref instead of a hash (I think).