Please help me return multiple valus from a subroutine

M

mmasroorali

Dear All,
I am confused here. I want to return multiple values from a subroutine
where the first two are one dimensional arrays, the third one is a two
dimensional array. To return them together I had a naive approach like
this (rebuilt as a minimal example),

I want to assign ss1 to s1 etc.

#!/usr/bin/perl

use strict;
use warnings;

my (@s1, @s2, @s3) = mysub();

print "@s1\n";
print "@s2\n";
print "@s3\n";


sub mysub
{
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (@ss1, @ss2, @ss3);
}

I find that every thing gets assigned to @s1, where the last three are
addresses (possibly from @ss3).

Could please tell me how I can get the intended effect?

Regards.
 
A

A. Sinan Unur

(e-mail address removed) wrote in @z14g2000cwz.googlegroups.com:
I am confused here. I want to return multiple values from a subroutine
where the first two are one dimensional arrays, the third one is a two
dimensional array. To return them together I had a naive approach like
this (rebuilt as a minimal example),

From perldoc perlsub:

... If you return one or more aggregates (arrays and hashes),
these will be flattened together into one large indistinguishable
list.

The solution is to return references.
#!/usr/bin/perl

use strict;
use warnings;

my (@s1, @s2, @s3) = mysub();

print "@s1\n";
print "@s2\n";
print "@s3\n";


sub mysub
{
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (@ss1, @ss2, @ss3);
}

#!/usr/bin/perl

use strict;
use warnings;

my ($s1, $s2, $s3) = mysub();

print "@$s1\n";
print "@$s2\n";
print "@$s3\n";


sub mysub {
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (\@ss1, \@ss2, \@ss3);
}
__END__


Sinan
 
A

axel

I am confused here. I want to return multiple values from a subroutine
where the first two are one dimensional arrays, the third one is a two
dimensional array. To return them together I had a naive approach like
this (rebuilt as a minimal example),
I want to assign ss1 to s1 etc.
#!/usr/bin/perl

use strict;
use warnings;

my (@s1, @s2, @s3) = mysub();

See note below.
print "@s1\n";
print "@s2\n";
print "@s3\n";


sub mysub
{
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (@ss1, @ss2, @ss3);
}

I find that every thing gets assigned to @s1, where the last three are
addresses (possibly from @ss3).

As mysub() is returning arrays, the values will be flattened and, as you
found, all poured into @s1.

And the last three will indeed be addresses as they are references to
anonymous arrays.

One way is to return references to the arrays to be returned.


#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my ($s1, $s2, $s3) = mysub();

print "@$s1\n";
print "@$s2\n";
print "@{@$s3[0]} @{@$s3[1]} @{@$s3[2]}\n";

# Alternative method for seeing what returned for $s3

print Dumper($s3);

sub mysub {
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (\@ss1, \@ss2, \@ss3);
}
__END__

See: perldoc perlreftut

Axel
 
A

axel

#!/usr/bin/perl

use strict;
use warnings;

my ($s1, $s2, $s3) = mysub();

print "@$s1\n";
print "@$s2\n";
print "@$s3\n";

Although in this last case for $s3, to get at the actual values we would
need something like:

print "@{@$s3[$_]}\n" for 0 .. $#{@$s3};

(I did try to make a posting ealier but it seems have ended up in the
big bit bucket).
sub mysub {
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (\@ss1, \@ss2, \@ss3);
}
__END__

Axel
 
A

A. Sinan Unur

(e-mail address removed) wrote in @fe2.news.blueyonder.co.uk:
....

Although in this last case for $s3, to get at the actual values we
would need something like:

print "@{@$s3[$_]}\n" for 0 .. $#{@$s3};

print "@$_\n" for @$s3;

would probably be more legible (glad to see I am not the only one
occasionally piles a few too many curlies and derefs).

However, the actual question was not about printing an array of array
references, so I left the OP's code unmodified except for the bare
minimum changes needed to make it "work".

Sinan
 
C

Chris Mattern

Dear All,
I am confused here. I want to return multiple values from a subroutine
where the first two are one dimensional arrays, the third one is a two
dimensional array. To return them together I had a naive approach like
this (rebuilt as a minimal example),

I want to assign ss1 to s1 etc.

#!/usr/bin/perl

use strict;
use warnings;

my (@s1, @s2, @s3) = mysub();

This assigns everything returned by mysub to @s1.
print "@s1\n";
print "@s2\n";
print "@s3\n";


sub mysub
{
my @ss1 = ("1a", "1b", "1c");
my @ss2 = ("2a", "2b", "2c", "2d");
my @ss3 = (["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);
return (@ss1, @ss2, @ss3);
}

I find that every thing gets assigned to @s1, where the last three are
addresses (possibly from @ss3).

Yes, that's correct. That's what it's supposed to do. You need to
understand a what a subroutine returns; it doesn't return variables.
It returns a list. *One* list. So when you specified returning
three arrays, they got concatenated into one big list and it returned
that list. Thus, your subroutine call was equivalent to:

my (@s1, @s2, @s3) = ("1a", "1b", "1c", "2a", "2b", "2c", "2d",
["3aa", "3ab"], ["3ba", "3bb", "3bc"], ["3ca"]);

In assignments like this, the entire list goes into the first array.
Could please tell me how I can get the intended effect?

You'll need to use references if you want to return multiple arrays.
Then you can return a list of references.

--
Christopher Mattern

"Which one you figure tracked us?"
"The ugly one, sir."
"...Could you be more specific?"
 

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,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top