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

Okay guys I know how to return an array from a subroutine now (doooooooooh!!), however while working this out I tried to return a reference to an array with no real joy. In an attempt to get this working - for no other reason than I currently can't! - I wrote the following noddy script -
#!/usr/bin/perl -w use strict ; # sub xxrc_ref { # use strict ; # my @tester = qw(a b c d) ; my $rarray = \@tester ; # return $rarray ; } # ####################################################### # Variables # ####################################################### # my $row = undef ; my @response = undef ; # print "\n\t<****** SOR ******>\n" ; # @response = &xxrc_ref() ; # print "\n\tResponse = @response\n" ; # for $row (@response) { print "\n\t@$row\n" ; } # print "\n\t<****** EOR ******>\n\n" ;
When I run this I get the following -
<****** SOR ******> Response = ARRAY(0x12e50c) a b c d <****** EOR ******>
The problem I have with this is that the print of a,b,c,d should be on separate lines. The fact that they aren't makes me think I've got something horribly wrong but I can't see what. (I suspect a,b,c,d is being treated as a single element which is not what I want!) Any printable suggestions guys? Ronnie

Edit by castaway - fix broken code tag

Replies are listed 'Best First'.
Re: Array Reference (Again)
by Thelonius (Priest) on Oct 14, 2004 at 12:02 UTC
    You could either dereference the arrary reference right when the subroutine returns (changes in bold):
    #!/usr/bin/perl -w
    use strict ;
    #
    sub xxrc_ref {
    #
    use strict ;
    #
    my @tester = qw(a b c d) ;
    my $rarray = \@tester ;
    #
    return $rarray ;
    }
    #
    #######################################################
    #                     Variables                       #
    #######################################################
    #
    my $row                 = undef ;
    my @response            = undef ;
    #
    print "\n\t<****** SOR ******>\n" ;
    #
    @response = @{xxrc_ref()} ;
    #
    print "\n\tResponse = @response\n" ;
    #
    for $row (@response) {
       print "\n\t$row\n" ;
    }
    #
    print "\n\t<****** EOR ******>\n\n" ;
    
    (although you might just as well return an array in that case), or you could do this:
    #!/usr/bin/perl -w use strict; sub xxrc_ref { my @tester = qw(a b c d) ; my $rarray = \@tester ; return $rarray ; } ####################################################### # Variables # ####################################################### my $row; my $response; print "\n\t<****** SOR ******>\n" ; $response = &xxrc_ref() ; print "\n\tResponse = $response\n" ; for $row (@$response) { print "\n\t$row\n" ; } print "\n\t<****** EOR ******>\n\n" ;
Re: Array Reference (Again)
by amrangaye (Friar) on Oct 14, 2004 at 12:24 UTC

    The problem is that you're passing back an array reference from the sub, and using it as-is (without dereferencing).

    When you store this return value in yor @response array, the scalar value of the ref is stored as the first (and only) value of @response, and it is this you iterate over.

    You must dereference the value you're getting back first, before storing it in your array, as shown in the first post above. Do a perldoc perlreftut for more info

Re: Array Reference (Again)
by perlcapt (Pilgrim) on Oct 14, 2004 at 13:22 UTC
    The understanding of passing references is REALLY important for OO-Perl. I have spent much time playing with all the possible syntaxes of referencing and de-referencing. I'm sure there are always more things to learn about the subject. But I suggest you all discover all you can.
    Play with referenced multi-depth structures as much as possible. For example:
    #!/usr/bin/perl -w use strict; sub FullStru { # creates the structures my $stru = { # an annonymous hash (ad hoc hash) Level2a => { # another ad hoc hash Level3a => ['a'..'z'], # an ad hoc list at +level 3 Level3b => [1..10] # another }, Level2b => [ qw(word1 word2 word3) ] # an ad hoc list +at level 2 }; return $stru; # notice that this is a reference to an annoymous ha +sh with sub levels } sub DownOne { my $ref = shift; # by using a reference, you get the whole enchila +da if ( ref($ref) eq 'HASH') { # return the elements as list. No real practical value other # than as an exercise.. at least as much as I can see return 'ref to HASH', values %$ref; } elsif (ref($ref) eq 'ARRAY') { # return the elements as a list return 'ref to ARRAY', @$ref; } elsif (ref($ref) eq 'SCALAR') { return 'ref to SCALAR', $$ref; } elsif ( not ref($ref)) { return 'not a ref'; } # and so on.. } my $X = FullStru(); # create the structure and return a pointer to it # first level my @results1 = DownOne($X); print join("\n",@results1),"\n"; shift(@results1); # get rid of that first element # second level my $elem; foreach $elem (@results1) { print "\n\t",join("\n\t",DownOne($elem)),"\n"; } # and so on.. you get the idea


    The result should look like this:

    ref to HASH HASH(0x1d5f518) ARRAY(0x1d5f548) ref to HASH ARRAY(0x22526c) ARRAY(0x1d5f488) ref to ARRAY word1 word2 word3
      ++perlcapt...short and sweet. There is one misleading aspect to the code, however:

      if ( ref($ref) eq 'HASH') { # return the elements as list. No real practical value other # than as an exercise.. at least as much as I can see return 'ref to HASH', values %$ref; } elsif (ref($ref) eq 'ARRAY') { # return the elements as a list return 'ref to ARRAY', @$ref; } elsif (ref($ref) eq 'SCALAR') { return 'ref to SCALAR', $$ref; } elsif ( not ref($ref)) { return 'not a ref'; } # and so on.. }

      You don't list all reference types; missing are: REF, CODE, and GLOB.

      Maybe I'm just picking nits :)

      Jon

      ++perlcapt from me also.
      Read your bio - Welcome abord cap'n!
      BTW, what a great name for a boat: Mother of Perl!

      TheEnigma