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

I am having a problem returning data from a sub. I declare an array while calling a sub at the same time so it will return the data. It works unless I need to do a for loop.

Please review the code:
use strict; use warnings; my $test = 'DATA'; my @test_1_data = test_1($test); my @test_2_data = test_2($test); sub test_1{ read( DATA, my $foo1, 0x04 ); read( DATA, my $foo2, 0x04 ); read( DATA, my $foo3, 0x04 ); read( DATA, my $foo4, 0x04 ); return ( $foo1, $foo2, $foo3, $foo4 ); } sub test_2{ for(0 .. 3){ read( DATA, my $foo1, 0x04 ); read( DATA, my $foo2, 0x04 ); read( DATA, my $foo3, 0x04 ); read( DATA, my $foo4, 0x04 ); return ( $foo1, $foo2, $foo3, $foo4 ); #should return "belo +ngs to sub_2" 4 times } #for a total of 0 +x10 in length each loop } print ( "\nsub test_1:\n" ); print $_ for(@test_1_data), "\n\n"; print "sub test_2:\n"; print $_ for(@test_2_data), "\n"; #should print "belongs to sub_2" 4 t +imes on the same line. __DATA__ belongs to sub_1belongs to sub_2belongs to sub_2belongs to sub_2belong +s to sub_2

Any help would be very much appreciated :)

EDIT: Solution below, return will exit the loop.
sub test_2{ my @array; for(0 .. 3){ read( DATA, my $foo1, 0x04 ); read( DATA, my $foo2, 0x04 ); read( DATA, my $foo3, 0x04 ); read( DATA, my $foo4, 0x04 ); push (@array, ($foo1, $foo2, $foo3, $foo4 )); #push to arr +ay while inside of for loop } return (@array); #return it after all loop iterations are complete }

Thanks everyone :)

Replies are listed 'Best First'.
Re: sub will not return data correctly (the way i want it to!!)
by toolic (Bishop) on Jun 18, 2015 at 00:19 UTC
    The return is executed after the 1st iteration of the for loop. This means you exit the sub after only 1 time through the loop, not 4 times.
      Oh, ok i was unaware of that until now. I guess i will push all data onto an array then as said in CB.

        You can also call the function 4 times instead:

        my @test_1_data = test_1($test); my @test_2_data; push @test_2_data, test_1( $test ) for 1 .. 4;
        Notice that test_2() is not even called. A for loop around the first sub accomplishes the same goal.

        jeffa

        L-LL-L--L-LL-L--L-LL-L--
        -R--R-RR-R--R-RR-R--R-RR
        B--B--B--B--B--B--B--B--
        H---H---H---H---H---H---
        (the triplet paradiddle with high-hat)
        
Re: sub will not return data correctly (the way i want it to!!)
by aaron_baugher (Curate) on Jun 18, 2015 at 00:24 UTC

    When you call your second subroutine, it's going to start through the first loop of your for(), do the four reads, then return. It's never going to do the other 3 loops.

    If you want to do the loop four times and then return a list of all the results, you can do that. Create an array before your for() loop starts, then replace your return with a push to that array:

    push @results, $foo1, $foo2, $foo3, $foo4;

    Then after the for() loop is finished, return @results.

    Aaron B.
    Available for small or large Perl jobs and *nix system administration; see my home node.

Re: sub will not return data correctly (the way i want it to!!)
by jdporter (Paladin) on Jun 18, 2015 at 00:22 UTC

    Maybe <DATA> is out of data by the time you get to test_2?

      0x10 = 16 characters for first sub
      0x40 = 64 characters for second sub

      it is easy to see that in sub 2 it is reading 0x40 (64) in length and that __DATA__ is 0x50(80) in length.
      __DATA__ is 0x40 in length for sub test_2. Each iteration of the for loop should return 0x10 in length.

        return returns from the subroutine. It doesn't push data through a channel. If you want to return a collection of data from multiple loop iterations, you'll have to collect it first.

Re: sub will not return data correctly (the way i want it to!!)
by james28909 (Deacon) on Jun 18, 2015 at 00:34 UTC
    Thanks everyone. It is sorted now. :)
    Was having a bit of a brain smerdge.

      There's definitely more than one way to do it.

      use strict; use warnings; sub test { read( DATA, my $foo1, 0x04 ); return $foo1; } sub test_b { my @array; for my $i ( 0 .. 15 ) { read( DATA, $array[$i], 0x04 ); } return @array; } print "\ntest_1:\n"; print test() for ( 1..4 ); print "\ntest_2:\n"; print test() for 1..15, "\n"; print "\ntest_3:\n"; print test_b(), "\n" ; __DATA__ belongs to test1belongs to test2belongs to test2belongs to test2belong +s to test2belongs to test3belongs to test3belongs to test3belongs to +test3