Trouble Passing Array Containing Hash to Subroutine

S

Scott

All:

I am using Perl 5.8.0 on Red Hat Linux release 9 (Shrike).
I am attempting to pass a reference to an array whose elements are a
hash. When I go to generalize my code and pass a reference to this
array to a subroutine, the results I get back are unexpected.

Here is my annotated test program:

#!/usr/bin/perl -w

#Create empty array arySTUFF.
my @arySTUFF=();

#Create hash to map 0,1,2 to data element names
# corresponding to database column names.
my %hSTUFF_VARLIST=(0=>'DATE_AUTH',
1=>'FILENAME',
2=>'CLAIMS');

#Push an anonymous hash into the array arySTUFF
# making it the first (zeroth) element of the array.
# Note that I am initializing each of the hash elements
# in case there is no data coming in from my data source
# I will have some value.
push(@arySTUFF,{DATE_AUTH => 'XXXXXXXX',
FILENAME => 'No FileName',
CLAIMS => -1});

#Initialize the three hash elements for this first array element
# and then print out the results to see if it worked.
$$arySTUFF[0]->{$hSTUFF_VARLIST{0}}="20041116";
$$arySTUFF[0]->{$hSTUFF_VARLIST{1}}="BIGDATAFILE.TXT";
$$arySTUFF[0]->{$hSTUFF_VARLIST{2}}=12345;
print "DATE_AUTH=",$$arySTUFF[0]{$hSTUFF_VARLIST{0}},"\n";
print "FILENAME=",$$arySTUFF[0]{$hSTUFF_VARLIST{1}},"\n";
print "CLAIMS=",$$arySTUFF[0]{$hSTUFF_VARLIST{2}},"\n";

#The next line shows that $$arySTUFF[0] is a HASH reference
# at some memory location.
print "ARYSTUFF[0]=",$$arySTUFF[0],"\n";
#The next line shows the actual value in the hash reference
# for FILENAME. This works.
print "ARYSTUFF[0]=>",$$arySTUFF[0]->{FILENAME},"\n";

#Pass a reference to the array arySTUFF and hash hSTUFF_VARLIST.
# Note that I have no problem with hash ref at all, just the array
ref.
print "===TRYSUB===\n";
TrySub(\@arySTUFF,\%hSTUFF_VARLIST);

#Use a subroutine to generalize the arrays and the hashes.
sub TrySub {
my @aryData = @{$_[0]};
my $hData = $_[1];
print "Num Rows==>",$#aryData+1,"\n";
#The following line show a difference HASH memory location
# than the one above.
print "ARYDATA[0]=",$aryData[0],"\n";
#The following prints out the initialization value "No Filename"
# rather than the expected BIGDATAFILE.TXT.
print "ARYDATA[0]=>",$aryData[0]->{FILENAME},"\n";

#Just in case, let's check if arySTUFF is messed up...it isn't.
print "\nCheck: Original arySTUFF is okay\n";
print "ARYSTUFF[0]=",$$arySTUFF[0],"\n";
print "ARYSTUFF[0]=>",$$arySTUFF[0]->{FILENAME},"\n";

}

exit;


Here are the results of this test program:

DATE_AUTH=20041116
FILENAME=BIGDATAFILE.TXT
CLAIMS=12345
ARYSTUFF[0]=HASH(0x80660b0)
ARYSTUFF[0]=>BIGDATAFILE.TXT
===TRYSUB===
Num Rows==>1
ARYDATA[0]=HASH(0x804ca88)
ARYDATA[0]=>No FileName

Check: Original arySTUFF is okay
ARYSTUFF[0]=HASH(0x80660b0)
ARYSTUFF[0]=>BIGDATAFILE.TXT


When the subroutine prints out "No Filename", I am confused as to why
this happens. I am expecting to see BIGDATAFILE.TXT. Any help with
this would be very greatly appreciated. (I'd hate to hard code my
program when a nice subroutine would be better!)

Thanks!
Scott
 
G

Gunnar Hjalmarsson

Scott said:
I am attempting to pass a reference to an array whose elements are a
hash. When I go to generalize my code and pass a reference to this
array to a subroutine, the results I get back are unexpected.

Here is my annotated test program:

#!/usr/bin/perl -w

Why not

use strict;

?? If you had had strictures enabled, you would have been able to figure
out what mistake you made.
 
J

Jim Keenan

Scott said:
All:

I am using Perl 5.8.0 on Red Hat Linux release 9 (Shrike).
I am attempting to pass a reference to an array whose elements are a
hash. When I go to generalize my code and pass a reference to this
array to a subroutine, the results I get back are unexpected.

Here is my annotated test program:

#!/usr/bin/perl -w

Why haven't you used this?

use strict;
#Create empty array arySTUFF.
my @arySTUFF=();

Your choice of variable names creates unnecessary line noise. Why is
everything named some variant of 'STUFF'?
#Create hash to map 0,1,2 to data element names
# corresponding to database column names.
my %hSTUFF_VARLIST=(0=>'DATE_AUTH',
1=>'FILENAME',
2=>'CLAIMS');

If you're using non-negative integers for the keys of a hash, you might
as well use an array instead, since arrays are automatically indexed by
non-negative integers.

I copied-and-pasted your code, ran it (it did compile), and got no
output whatsoever. So I'm not able to directly comment on your problem.
However, I *strongly* recommend that before proceeding further you get
familiar with the Data::Dumper module, as it is the most widely used way
to dump and examine the contents of variables, particularly multi-level
arrays and hashes such as you are using.

% perldoc Data::Dumper

Jim Keenan
 
A

A. Sinan Unur

(e-mail address removed) (Scott) wrote in
I am attempting to pass a reference to an array whose
elements are a hash.

I have no idea what this sentence means.
When I go to generalize my code and pass a reference to this
array to a subroutine, the results I get back are unexpected.
Ditto.

Here is my annotated test program:

#!/usr/bin/perl -w

use warnings;

Incidentally, you really ought to make sure you fix everything perl warns
you about before posting here. Have you read the posting guidelines for
this group?

D:\Home>perl t7.pl
Warning: Use of "ref" without parentheses is ambiguous at t7.pl line 39.
Useless use of concatenation (.) or string in void context at t7.pl line
40.

And, why do you not have

use strict;

D:\Home>perl t7.pl
Warning: Use of "ref" without parentheses is ambiguous at t7.pl line 42.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 26.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 27.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 28.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 29.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 30.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 31.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 35.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 38.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 60.
Global symbol "$arySTUFF" requires explicit package name at t7.pl line 61.
Execution of t7.pl aborted due to compilation errors.

What can I say? Isn't that obvious enough?
#Create empty array arySTUFF.

Useless comments are worse than no comments.
my @arySTUFF=();

Declare your variables in the smallest applicable scope.
#Create hash to map 0,1,2 to data element names
# corresponding to database column names.
Why?

my %hSTUFF_VARLIST=(0=>'DATE_AUTH',
1=>'FILENAME',
2=>'CLAIMS');

Choosing the correct data structure for your problem is essential. In this
case, why use a hash when you are indexing using nonnegative integers?
#Push an anonymous hash into the array arySTUFF
# making it the first (zeroth) element of the array.

This amount of noise is really uncalled for and coupled with the really bad
variable names makes your code very hard to read. In case you haven't
noticed, we know that @arySTUFF is an array not because of the prefix 'ary'
but because of the @ sign in front of it. Variable names should be
descriptive of the information variables hold.
# Note that I am initializing each of the hash elements
# in case there is no data coming in from my data source
# I will have some value.

Sigh! What data source?
push(@arySTUFF,{DATE_AUTH => 'XXXXXXXX',
FILENAME => 'No FileName',
CLAIMS => -1});

#Initialize the three hash elements for this first array element
# and then print out the results to see if it worked.
$$arySTUFF[0]->{$hSTUFF_VARLIST{0}}="20041116";
$$arySTUFF[0]->{$hSTUFF_VARLIST{1}}="BIGDATAFILE.TXT";
$$arySTUFF[0]->{$hSTUFF_VARLIST{2}}=12345;

Why $$?
print "DATE_AUTH=",$$arySTUFF[0]{$hSTUFF_VARLIST{0}},"\n";
print "FILENAME=",$$arySTUFF[0]{$hSTUFF_VARLIST{1}},"\n";
print "CLAIMS=",$$arySTUFF[0]{$hSTUFF_VARLIST{2}},"\n";

This makes me think, what's up with %hSTUFF_VARLIST?

Also, please use

Data::Dumper

for this purpose.
#The next line shows that $$arySTUFF[0] is a HASH reference
# at some memory location.
print "ARYSTUFF[0]=",$$arySTUFF[0],"\n";
#The next line shows the actual value in the hash reference
# for FILENAME. This works.
print "ARYSTUFF[0]=>",$$arySTUFF[0]->{FILENAME},"\n";

#Pass a reference to the array arySTUFF and hash hSTUFF_VARLIST.
# Note that I have no problem with hash ref at all, just the array
ref.
print "===TRYSUB===\n";
TrySub(\@arySTUFF,\%hSTUFF_VARLIST);

#Use a subroutine to generalize the arrays and the hashes.
sub TrySub {
my @aryData = @{$_[0]};
my $hData = $_[1];
print "Num Rows==>",$#aryData+1,"\n";

There is no need for $#aryData+1. Impose scalar context on @aryData to get
the number of elements in @aryData.
#The following line show a difference HASH memory location
# than the one above.
print "ARYDATA[0]=",$aryData[0],"\n";
#The following prints out the initialization value "No Filename"
# rather than the expected BIGDATAFILE.TXT.
print "ARYDATA[0]=>",$aryData[0]->{FILENAME},"\n";

#Just in case, let's check if arySTUFF is messed up...it isn't.
print "\nCheck: Original arySTUFF is okay\n";
print "ARYSTUFF[0]=",$$arySTUFF[0],"\n";
print "ARYSTUFF[0]=>",$$arySTUFF[0]->{FILENAME},"\n";

}

My head hurts!
When the subroutine prints out "No Filename", I am confused as to why
this happens. I am expecting to see BIGDATAFILE.TXT. Any help with
this would be very greatly appreciated. (I'd hate to hard code my
program when a nice subroutine would be better!)

Please read the posting guidelines for this group. This document is posted
here regularly or you can find it on the WWW at
http://mail.augustmail.com/~tadmc/clpmisc/clpmisc_guidelines.text

I have a very hard time understanding why you are doing what you are doing.

#!/usr/bin/perl

use strict;
use warnings;


my @columns = qw(DATE_ATUH FILENAME CLAIMS);

my @claims;

# I think the line below would be a maintainence nightmare

push @claims, {
$columns[0] => '20041116',
$columns[1] => 'BIGDATAFILE.TXT',
$columns[2] => 12345,
};

print TrySub(claims => \@claims, columns => \@columns);

sub TrySub {
my %args = @_;
for my $claim (@{ $args{claims} }) {
for my $column (@{ $args{columns} }) {
print "$column = $claim->{$column}\n";
}
}
}


Sinan.
 
G

Gunnar Hjalmarsson

Jim said:
I copied-and-pasted your code, ran it (it did compile), and got no
output whatsoever.

Funny. It sure doesn't compile for me with strictures enabled. This is
the first line where Perl complains:

$$arySTUFF[0]->{$hSTUFF_VARLIST{0}}="20041116";

The first '$' character should not be there, since the declared variable
is the array @arySTUFF.

Etc., etc.
 
A

A. Sinan Unur

D:\Home>perl t7.pl
Warning: Use of "ref" without parentheses is ambiguous at t7.pl line 39.
Useless use of concatenation (.) or string in void context at t7.pl line
40.

The warnings above are due to comments wrapping in my editor.

Sinan
 
J

Jim Keenan

I re-tried this, saving the code to file in a different way. This time
I did get output, albeit with warnings.
Funny. It sure doesn't compile for me with strictures enabled. This is
the first line where Perl complains:

I tried it first verbatim, i.e., without strictures.
 
M

Michael Erskine

Jim said:
If you're using non-negative integers for the keys of a hash, you might
as well use an array instead, since arrays are automatically indexed by
non-negative integers.

Not if your non-negative integer keys are non-contiguous -- you fall foul of
deriving too much specific information from this limited context in your
tirade of poor-programming accusations.

Love,
Bunky
 
S

slhecht

As (violently) suggested, I added "use strict;" and was able to
determine the problem. Thanks for the suggestions...I will try to be
much more careful in my posts in the future...sorry for any trouble...
 
S

slhecht

As (violently) suggested, I added "use strict;" and was able to
determine the problem. Thanks for the suggestions...I will try to be
much more careful in my posts in the future...sorry for any trouble...
 
T

Tad McClellan

Michael Erskine said:
Not if your non-negative integer keys are non-contiguous -- you fall foul of
deriving too much specific information from this limited context in your
tirade of poor-programming accusations.


Tirade? What tirade?

Looks like a calmly delivered BTW to me.

And if the OP actually had non-contiguous indexes, then the example
should *show* non-contiguous indexes, else he could fall afoul of
getting non-applicable comments about it.

We are not mind readers, we can only go by what we are told (or by
what is implied in examples).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top