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

Hi monks, I have a problem, I have written a sub-routine that looks for pairs of things in an array. However, I want to do this for 5 arrays and so repreat the code for all five (couldn't think of an efficient way to do it). The problem is that when I call the sub-routine, as below only the @pairs and @pairs5 values are printed. If i comment out the printing of @pairs, the values of @pairs2 are printed etc. I was wondering if anyone new whether this is because I am returning more than one value from the sub-routine?? And also if anyone could suggest a more efficient way of writing the code? Thanks, x
my @pairs = get_pairs (@segment1); my @pairs2 = get_pairs (@segment2); my @pairs3 = get_pairs (@segment3); my @pairs4 = get_pairs (@segment4); my @pairs5 = get_pairs (@segment5); print "my pairs are: @pairs"; print "my pairs2 are: @pairs2"; print "my pairs3 are: @pairs3"; print "my pairs4 are: @pairs4"; print "my pairs5 are: @pairs5"; sub get_pairs { (@segment1, @segment2, @segment3, @segment4, @segment5) = @_ +; my (@pairs, @pairs2, @pairs3, @pairs4, @pairs5); my $i; my $nn_pair; # find and print all nn pairs from the sequence. foreach $i (1..$#segment1) { push @pairs, "$segment1[$i-1]$segment1[$i]\n"; } return @pairs; foreach my $k (1..$#segment2) { push @pairs2, "$segment2[$k-1]$segment2[$k]\n"; } return @pairs2; foreach my $j (1..$#segment3) { push @pairs3, "$segment3[$j-1]$segment3[$j]\n"; } return @pairs3; foreach my $h (1..$#segment4) { push @pairs4, "$segment4[$h-1]$segment4[$h]\n"; } return @pairs4; foreach my $m (1..$#segment5) { push @pairs5, "$segment5[$m-1]$segment5[$m]\n"; } return ( @pairs5); }

Replies are listed 'Best First'.
Re: subroutines + returning more than 1 value
by Abigail-II (Bishop) on Feb 28, 2003 at 12:36 UTC
    If you are doing:
    (@segment1, @segment2, @segment3, @segment4, @segment5) = @_;

    everything in @_ is assigned to @segment1, and nothing to the other arrays. This is because everything is flattened to one list.

    Furthermore, as soon as a subroutine encounters a return statement, it does just that: return from the subroutine. No other statements in the sub are called.

    What you probably want is pass references to the arrays in the sub, and return a list of references to arrays.

    Perhaps you should first actually pick up a book and take the time to learn Perl. Then you will finish your assignment a lot sooner than coming to be spoonfed over and over again on Perlmonks. How many very basic questions have you asked here related to pairing up base pairs?

    Abigail

Re: subroutines + returning more than 1 value
by caedes (Pilgrim) on Feb 28, 2003 at 12:24 UTC
    Once you call 'return' in a subroutine the subroutine stops executing and control is returned to the caller. Therefore, no code after the first return is ever executed. Also, well you call the sub with the first array as an argument, it runs the get_pairs() function right then. It doesn't wait around for you to give it the other 4 arrays.

    It looks to me like you have a few very odd ideas about how functions work in perl. Might I suggests some reading: perlsub

    I'd suggest looking into information on

    1. Using arrays as arguments to functions
    2. Returning values from functions
    3. Returning arrays from functions

    -caedes

Re: subroutines + returning more than 1 value
by robartes (Priest) on Feb 28, 2003 at 12:38 UTC
    Here's a quickie that does what you ask, based on an array of arrays.
    #!/usr/local/bin/perl -w use strict; my @segment; $segment[0]=[ qw(one two three four) ]; $segment[1]=[ qw(red blue green yellow) ]; $segment[2]=[ qw(a b c d) ]; print "Pairs for segment ".($_+1)." are: \n", join "\n", get_pairs($se +gment[$_]), "\n" for (0..2); sub get_pairs { my $aryref=shift; my @pairs; push @pairs, $aryref->[$_-1].$aryref->[$_] for (1 .. $#$aryref ); return @pairs; } __END__ Pairs for segment 1 are: onetwo twothree threefour Pairs for segment 2 are: redblue bluegreen greenyellow Pairs for segment 3 are: ab bc cd
    I strongly suggest that you read some documentation. Learning Perl is a good place to start.

    CU
    Robartes-

Re: subroutines + returning more than 1 value
by OM_Zen (Scribe) on Feb 28, 2003 at 17:19 UTC
    Hi ,

    The arrays when input to a function will be obtained as a list and hence your first array alone gets assigned from the @_ , the array have to be passed as REFERENCE and then the return exits from the function and hence you can use only one of the returns and get the value from the calling part of it
    use Data::Dumper; my @seg1 = ("fkgskfgskfgksf","kshflkshfkls"); my @seg2 = ("kgskfgskf","sjfgsjfgjsgfksf"); #create references my $seg1 = \@seg1; my $seg2 = \@seg2; my $seg3 = \@seg3; my $seg4 = \@seg4; my $seg5 = \@seg5; my @pairs = get_pairs($seg1,$seg2,$seg3,$seg4,$seg5); print Dumper \@pairs; sub get_pairs { my @seg_pairs = @_; map {for my $i (1..scalar(@$_)){ push (@pairs , "$_->[$i-1] $_->[$i]\n");} }@seg_pairs; return @pairs; }


    The usages of references are many and this is one of the ways to do it

    the reference is pushed to an array and the array is passed to the function

    the arrays are gotten by doing a dereference and then an array is pushed for that you should have

    the array is obtained and the using Data::Dumper is printed and then you could do that you rerquire with it

      Hi ,

      The function get_pairs has to be written this way . The previous node has to be ignored as the usage of map is not so much appropriate , though we get the solution as required by that
      use Data::Dumper; my @seg1 = ("one","two","three"); my @seg2 = ("four","five"); #create references my $seg1 = \@seg1; my $seg2 = \@seg2; my $seg3 = \@seg3; my $seg4 = \@seg4; my $seg5 = \@seg5; my @pairs = get_pairs($seg1,$seg2,$seg3,$seg4,$seg5); print Dumper \@pairs; sub get_pairs { my @seg_pairs = @_; my @pairs = map { local $arr_frst_scalar = $_; map { ["$arr_frst_scalar->[$_-1] $arr_frst_scala +r->[$_]"] ; }1..scalar(@$_) }@seg_pairs; return @pairs; } __END__ $VAR1 = [ [ 'one two' ], [ 'two three' ], [ 'three' ], [ 'four five' ], [ 'five' ] ];