#### Do you have a question? Post it now! No Registration Necessary.  Now with pictures!

•  Subject
• Author
• Posted on

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

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

Regards.

mmasroorali@cse.buet.ac.bd wrote in news:1115465798.208509.219860

> 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
--
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:

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

> #!/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 "@\n" for 0 .. \$#;

(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

axel@white-eagle.co.uk wrote in news:EF5fe.40458\$Cq2.7608
@fe2.news.blueyonder.co.uk:

>>> I am confused here. I want to return multiple values from a
>>> subroutine

....

> Although in this last case for \$s3, to get at the actual values we
> would need something like:
>
> print "@\n" for 0 .. \$#;

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

--
(reverse each component and remove .invalid for email address)

comp.lang.perl.misc guidelines on the WWW:

mmasroorali@cse.buet.ac.bd wrote:

> 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

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

--
Christopher Mattern

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

mmasroorali@cse.buet.ac.bd wrote:
> 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

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 "@ @ @\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