LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 04-20-2005, 03:42 PM   #1
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 927

Rep: Reputation: 30
Passing hash of hashes as a parameter (Perl)


Hi all,
I've got a hash (in perl) which happens to be a hash of hashes. I'm trying to pass it as a parameter to a subroutine, but somehow the subroutine only receives a very, very reduced copy of it.
A foreach loop through all keys in the hash reveals that only one element is present, and the element does not contain the hash that it ought to.

in other words...

Code:
my %hash = some stuff.  It's been tested up here and is complete.
my $string = function(%hash);


sub function
{
   %localHash = shift(@_);
   foreach my $key (keys %hash)
   {
       print STDOUT "key: $key, hash{$key}->{ELEMENT}: $hash{$key}->{ELEMENT}\n";
   }
   print STDOUT "--------------------------"
   #concatenate all $hash{$key}->{ELEMENT}'s onto a string
   #return that string
}
That prints out:

key: CHA, hash{CHA}->{ELEMENT}:
--------------------------

(there should be about 15 more keys after the first CHA, and $hash{CHA}->{ELEMENT} should definitely be populated. The string that I return is empty.)

If I don't pass the hash as a parameter, and instead just treat it as global and access the global variable in the subroutine, all works fine. But I'd rather not do that

I'm sort of stumped. Can anyone see what I'm doing wrong here?
Many thanks...
 
Old 04-20-2005, 10:32 PM   #2
johnMG
Member
 
Registered: Jul 2003
Location: CT, USA
Distribution: Debian Sarge (server), Etch (work/home)
Posts: 601

Rep: Reputation: 31
You probably want to pass a reference to the hash into function():

my $string = function( \%hash );

Then, inside your function(), you need to dereference it to use it. See "man perlreftut".

Last edited by johnMG; 04-20-2005 at 10:36 PM.
 
Old 04-21-2005, 10:03 AM   #3
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 927

Original Poster
Rep: Reputation: 30
Outstanding

My subroutine looks sort of like a swear word in a comic strip, but it works!
 
Old 04-21-2005, 12:10 PM   #4
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 30
The reason your original script did not work was because of the way perl handles list arguments to functions. All arguments are evaluated in a list context and concatenated, which are then available to the subroutine in the @_ list. When hashes are evaluated in a list context, the resulting list is just the key/value pairs. Thus when you passed the hash to subroutine, @_ contained (key1,value1,key2,value2,etc). Then you shifted the first value off and fed it to hash, which would take only key1 and make a hash consisting of one key and no values. You probably meant to do

Code:
%localHash = @_;
which would take the entire list of keys and values and re-form a hash. This is slower than using a hash reference though, because the subroutine makes a local copy. The gotcha there for a hash-of-hashes is that it is a "shallow" copy, and all the values refer to the original hashes that were the values, not copies of those hashes.

Last edited by puffinman; 04-21-2005 at 12:20 PM.
 
Old 04-21-2005, 05:10 PM   #5
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 927

Original Poster
Rep: Reputation: 30
What I ended up doing was this:

Code:
my %hash = some stuff.  It's been tested up here and is complete.
my $string = function(%hash);

sub function {
    my ($localConfig) = @_[$[];
    my $key;
    my $string;
    
    foreach $key (sort keys %{$localConfig}) {
	$string = $string . "'". trim(${$$localConfig{$key}}{ELEMENT}) . "',";
    }
    
    #remove the last ','
    chop $string;
    
    return $string;
}
which surprisingly enough, works.

I understand your explanation (in a hazy sort of way). I also understand (in an even hazier way) wtf "my ($localConfig) = @_[$[];" is doing Are your method and what this is doing roughly the same thing, and yours is just written more simply?
 
Old 04-21-2005, 06:35 PM   #6
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 30
Wow, I'm not sure what exactly you're doing in that statement (my ($localConfig) = @_[$[];). Is that even valid under use strict? Does it throw out a warning under use warnings or the -w switch?

Though you seem to be using a reference there, you are not using it in the way that earlier posts directed. They meant to take the reference outside the function, then dereference inside, like so:

Code:
my %coolhash = qw(this is a hash);
my $hashref = \%coolhash;

my $result = mysub($hashref);

sub mysub {
    my $reference = shift @_;
    my %localhash = %{$reference};

    # do something with localhash

    return "success!";
}
If you wanted to pass the whole hash with no references involved:

Code:
my %coolhash = qw(these hashes are cool);

my $result = mysub(%coolhash);

sub mysub {
    my %localhash = @_;

    # do something with local hash

    return "of course it worked";
}

Last edited by puffinman; 04-21-2005 at 06:39 PM.
 
Old 04-21-2005, 07:33 PM   #7
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 927

Original Poster
Rep: Reputation: 30
Valid under use strict, yes. Valid under -w ...who knows. There're a whole bunch of required includes that -w kicks out at, so in order for anything to work I've got to keep -w out of the equation :-/

Basically, what I understand of the @_[$[] is that it's somehow getting the first element of @_ (that's what the $[ is doing), and somehow the enclosing brackets there are doing something to make it a hash. I'm not clear on that part yet.

I think most of my issues resulted from the fact that the hash is a hash of references to hashes...so on top of dereferencing the hash that's passed into the function, I've got to dereference each element to actually get at what I need to access :-)
 
Old 04-21-2005, 08:03 PM   #8
puffinman
Member
 
Registered: Jan 2005
Location: Atlanta, GA
Distribution: Gentoo, Slackware
Posts: 217

Rep: Reputation: 30
Alright, I looked up $[ in the camel book. This variable stands for the first index of an array, and defaults to 0. Apparently if you set it to 1 then you can get more awk-like behavior. In any case, @_[$[] is thus equivalent to @_[0], which is equivalent to a "list slice" consisting of only the first element of @_, which is equivalent to $_[0], which is equivalent to the value returned by shift @_. So I think @_[$[] is unnecessarily obfuscated.
 
Old 04-21-2005, 08:18 PM   #9
rose_bud4201
Member
 
Registered: Aug 2002
Location: St Louis, MO
Distribution: Xubuntu, RHEL, Solaris 10
Posts: 927

Original Poster
Rep: Reputation: 30
You are my hero. Seriously

I was absolutely baffled about what the [] was doing in there...this clears things up immensely (and entertaining though it may be, I'll p'bly change the comic-strip swear-word looking thing to shift @_ just to simplify things...!)

Next step on my list of things to learn...list slices.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
setting up scp alias under bash - parameter passing problem gjr Linux - Newbie 4 06-08-2005 07:38 AM
weird behaviour with hashes in perl weird_guy Programming 0 06-22-2004 10:51 PM
passing anonymous hash in CGI hidden field wonderdog33 Programming 1 01-30-2004 12:19 PM
Passing parameter to kernel when booting from floppy NewtoSlack Slackware 1 10-10-2003 09:24 PM
parameter passing mechanisms dhanakom Programming 2 09-01-2003 05:15 PM


All times are GMT -5. The time now is 10:26 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration