Trouble Passing Array Containing Hash to Subroutine

Discussion in 'Perl Misc' started by Scott, Dec 5, 2004.

  1. Scott

    Scott Guest

    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
    Scott, Dec 5, 2004
    #1
    1. Advertising

  2. Scott wrote:
    > 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.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 6, 2004
    #2
    1. Advertising

  3. Scott

    Jim Keenan Guest

    Scott wrote:

    > 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
    Jim Keenan, Dec 6, 2004
    #3
  4. (Scott) wrote in
    news::

    > 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.
    A. Sinan Unur, Dec 6, 2004
    #4
  5. Jim Keenan wrote:
    > 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.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 6, 2004
    #5
  6. "A. Sinan Unur" <> wrote in
    news:Xns95B6C6FC57938asu1cornelledu@132.236.56.8:

    > 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
    A. Sinan Unur, Dec 6, 2004
    #6
  7. Scott

    Jim Keenan Guest

    Gunnar Hjalmarsson wrote:

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

    >


    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.
    Jim Keenan, Dec 6, 2004
    #7
  8. Jim Keenan wrote:

    > 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
    Michael Erskine, Dec 6, 2004
    #8
  9. Scott

    Guest

    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...
    , Dec 6, 2004
    #9
  10. Scott

    Guest

    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...
    , Dec 6, 2004
    #10
  11. Michael Erskine <> wrote:
    > Jim Keenan wrote:
    >
    >> 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.



    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).


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
    Tad McClellan, Dec 7, 2004
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    6
    Views:
    2,753
    Eric Bohlman
    Apr 4, 2005
  2. rp
    Replies:
    1
    Views:
    512
    red floyd
    Nov 10, 2011
  3. Dean
    Replies:
    3
    Views:
    178
  4. king
    Replies:
    5
    Views:
    182
  5. laredotornado

    Trouble passing arguments to subroutine

    laredotornado, Nov 5, 2010, in forum: Perl Misc
    Replies:
    2
    Views:
    94
    J├╝rgen Exner
    Nov 6, 2010
Loading...

Share This Page