Returning multiple values

J

J Krugman

I don't think I'll ever manage to learn all of Perl's little
quirks... I just discovered that Perl has two very different ways
of returning multiple values (see below). What's the rationale
for this ambiguous behavior?

If one defines "sub foo { (7, 8, 9) }", then "scalar foo()" evaluates
to 9. But if one defines "sub bar { my @x = (7, 8, 9) }", then
"scalar bar()" evaluates to 3.

Is there a way to get bar's behavior without the superfluous
assignment?

The more annoying problem is when one is using some function like
foo above written by someone else, and wants to get only the number
of values returned. Then it seems like the simplest way to do this
requires another superfluous assignment:

my $n = (my @x = foo());

or

my $n = do { my @x = foo() };

or

my $n = @{[foo()]};

Is there a way to code this that is both succinct and does not
require extraneous constructs? In other words, is there a way
(other than through a superfluous assignment) to tell perl (and
anyone reading the code) that "(7, 8, 9)" in the definition of foo
should be intepreted as an array, and not as a list?

Thanks!

jill
 
B

Bob Walton

J said:
I don't think I'll ever manage to learn all of Perl's little
quirks... I just discovered that Perl has two very different ways
of returning multiple values (see below). What's the rationale
for this ambiguous behavior?


It is not ambiguous -- it is the difference between the behavior
exhibited by the comma operator and that exhibited by an array. See:

perldoc -q "list and an array"

or

perldoc -q 'list and an array'

depending upon your OS.

If one defines "sub foo { (7, 8, 9) }", then "scalar foo()" evaluates
to 9. But if one defines "sub bar { my @x = (7, 8, 9) }", then
"scalar bar()" evaluates to 3.


The first is because scalar (7,8,9) applies the comma operator,
returning in each case the rightmost of the values on the two sides of
each comma. When you say scalar (@x), it returns the number of elements
in array @x. Two vastly different cases.

Is there a way to get bar's behavior without the superfluous
assignment?
The more annoying problem is when one is using some function like
foo above written by someone else, and wants to get only the number
of values returned. Then it seems like the simplest way to do this
requires another superfluous assignment:

my $n = (my @x = foo());

or

my $n = do { my @x = foo() };

or

my $n = @{[foo()]};


Try:

my $n=()=foo();
 
J

J Krugman

In said:
J said:
The more annoying problem is when one is using some function like
foo above written by someone else, and wants to get only the number
of values returned. Then it seems like the simplest way to do this
requires another superfluous assignment:

my $n = (my @x = foo());

or

my $n = do { my @x = foo() };

or

my $n = @{[foo()]};

my $n=()=foo();


OK, but what does it mean? What does perl do when it executes the
statement

() = (7, 8, 9);

? Does the above evaluate to some sort of anonymous array?

Thanks,

jill
 
B

Bob Walton

J said:
....
OK, but what does it mean? What does perl do when it executes the
statement

() = (7, 8, 9);
? Does the above evaluate to some sort of anonymous array?


Look it up:

perldoc perldata

in the "List value constructors" section.
 
B

Bob Walton

J said:
OK, I read that section, but it says nothing whatsoever about
assigning to ().

Does anybody know what Perl does when one assigns a list to () (as
shown above)?


Here is the relevant section from perldata, which explicitly discuss the
assignment

$n=()=$somevar=~/some pattern/g;

which is just like:

$n=()=(7,8,9);

from a basic perspective, with the () acting to force a list-context
evaluation of the right-hand-side of the second = :

"An exception to this [assignment to a list of lvalues] is that you may
assign to undef in a list. This is useful for throwing away some of the
return values of a function:

($dev, $ino, undef, undef, $uid, $gid) = stat($file);

List assignment in scalar context returns the number of elements
produced by the expression on the right side of the assignment:

$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count

This is handy when you want to do a list assignment in a Boolean
context, because most list functions return a null list when finished,
which when assigned produces a 0, which is interpreted as FALSE.

It's also the source of a useful idiom for executing a function or
performing an operation in list context and then counting the number of
return values, by assigning to an empty list and then using that
assignment in scalar context. For example, this code:

$count = () = $string =~ /\d+/g;

will place into $count the number of digit groups found in $string. This
happens because the pattern match is in list context (since it is being
assigned to the empty list), and will therefore return a list of all
matching parts of the string. The list assignment in scalar context will
translate that into the number of elements (here, the number of times
the pattern matched) and assign that to $count. Note that simply using

$count = $string =~ /\d+/g;

would not have worked, since a pattern match in scalar context will only
return true or false, rather than a count of matches."
....
 
J

James Willmore

In <[email protected]> Bob Walton




OK, I read that section, but it says nothing whatsoever about assigning to
().

Does anybody know what Perl does when one assigns a list to () (as shown
above)?

from perldoc perldata ("List value constructors")
...
It's also the source of a useful idiom for executing a
function or performing an operation in list context and
then counting the number of return values, by assigning to
an empty list and then using that assignment in scalar
context. For example, this code:

$count = () = $string =~ /\d+/g;

will place into $count the number of digit groups found in
$string. This happens because the pattern match is in
list context (since it is being assigned to the empty
list), and will therefore return a list of all matching
parts of the string. The list assignment in scalar context
will translate that into the number of elements (here, the
number of times the pattern matched) and assign that to
$count.
...

You're assigning the return value of the subroutine to an empty list and
it's being evaluated as such (a list).

So,
my $n=()=foo();

the return value(s) of sub foo will go into the empty list (and populate
it). Because you're evaluating a list in scalar context, you'll get the
number of values in the list :) If you do:
my $n=foo();

You'll get the last value, as demonstrated by the following one liner:
jim@maxine:~> perl -e 'sub x{ qw(a b c d) };$count = x();print "$count\n"'
d
jim@maxine:~>

instead of
jim@maxine:~> perl -e 'sub x{ qw(a b c d) };$count = () = x();print "$count\n"'
4
jim@maxine:~>

which is what you wanted.

I used 'qw' to demonstrate what's going on. Using numbers, IMHO, clouds
the issue.

HTH

--
Jim

Copyright notice: all code written by the author in this post is
released under the GPL. http://www.gnu.org/licenses/gpl.txt
for more information.

a fortune quote ...
Ed Sullivan will be around as long as someone else has talent.
-- Fred Allen
 
J

J Krugman

In said:
J Krugman wrote:

Here is the relevant section from perldata, which explicitly discuss the
assignment
$n=()=$somevar=~/some pattern/g;
which is just like:

from a basic perspective, with the () acting to force a list-context
evaluation of the right-hand-side of the second = :
"An exception to this [assignment to a list of lvalues] is that you may
assign to undef in a list. This is useful for throwing away some of the
return values of a function:
($dev, $ino, undef, undef, $uid, $gid) = stat($file);
List assignment in scalar context returns the number of elements
produced by the expression on the right side of the assignment:
$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count
This is handy when you want to do a list assignment in a Boolean
context, because most list functions return a null list when finished,
which when assigned produces a 0, which is interpreted as FALSE.
It's also the source of a useful idiom for executing a function or
performing an operation in list context and then counting the number of
return values, by assigning to an empty list and then using that
assignment in scalar context. For example, this code:
$count = () = $string =~ /\d+/g;
will place into $count the number of digit groups found in $string. This
happens because the pattern match is in list context (since it is being
assigned to the empty list), and will therefore return a list of all
matching parts of the string. The list assignment in scalar context will
translate that into the number of elements (here, the number of times
the pattern matched) and assign that to $count. Note that simply using
$count = $string =~ /\d+/g;
would not have worked, since a pattern match in scalar context will only
return true or false, rather than a count of matches."
...

Thanks. I've discovered that my perldata page is damaged goods:

List assignment in scalar context returns the number of
elements produced by the expression on the right side of
the assignment:

$x = (($foo,$bar) = (3,2,1)); # set $x to 3, not 2
$x = (($foo,$bar) = f()); # set $x to f()'s return count

This is handy when you want to do a list assignment in a
Boolean context, because most list functions return a null
list when finished, which when assigned produces a 0,
which is interpreted as FALSE.

The final element may be an array or a hash:

($a, $b, @rest) = split;
my($a, $b, %rest) = @_;

You can actually put an array or hash anywhere in the
...

It is not that old either (2003-09-11). This is unsettling.

jill
 
J

Jeff 'japhy' Pinyan

[posted & mailed]

OK, but what does it mean? What does perl do when it executes the

Briefly put, there are a few things you need to know here. First, that
assignment works right-to-left, so

my $n = () = foo();

is, precedence-wise:

my $n = ( () = foo() );

Second, you need to know that list-assignment:

@a = foo();
($b, $c) = foo();
($d) = foo();
# and even
() = foo();

will, in scalar context, return the number of values found on the
right-hand side of the assignment. Thus, if foo() returns 10 values, then

$x = @a = foo();
$x = ($b, $c) = foo();
$x = ($d) = foo();
$x = () = foo();

all store 10 in $x, regardless of how many variables are being given
values from foo()'s return list.

And as an exercise to the reader, what do you expect

$a = ($b,$c) = ($d,$e,$f) = ('a' .. 'z');

to store in each of those variables? Remember precedence:

$a = (
($b,$c) = (
($d,$e,$f) = ('a' .. 'z')
)
);

(And also note that a list assignment in list context merely returns the
left-hand side, NOT the right-hand side.)
 
J

J Krugman

In said:
[posted & mailed]
Try:

my $n=()=foo();

OK, but what does it mean? What does perl do when it executes the
[/QUOTE]
Briefly put, there are a few things you need to know here. First, that
assignment works right-to-left, so
my $n = () = foo();
is, precedence-wise:
my $n = ( () = foo() );
Second, you need to know that list-assignment:
@a = foo();
($b, $c) = foo();
($d) = foo();
# and even
() = foo();
will, in scalar context, return the number of values found on the
right-hand side of the assignment. Thus, if foo() returns 10 values, then
$x = @a = foo();
$x = ($b, $c) = foo();
$x = ($d) = foo();
$x = () = foo();
all store 10 in $x, regardless of how many variables are being given
values from foo()'s return list.
And as an exercise to the reader, what do you expect
$a = ($b,$c) = ($d,$e,$f) = ('a' .. 'z');
to store in each of those variables? Remember precedence:
$a = (
($b,$c) = (
($d,$e,$f) = ('a' .. 'z')
)
);
(And also note that a list assignment in list context merely returns the
left-hand side, NOT the right-hand side.)

Thank you, that was very clear and helpful.

jill
 
B

Bob Walton

J said:
Thanks. I've discovered that my perldata page is damaged goods:
...

It is not that old either (2003-09-11). This is unsettling.

jill

Interesting. Mine is older than that (3/31/03). It's from:

This is perl, v5.8.0 built for MSWin32-x86-multi-thread
(with 1 registered patch, see perl -V for more detail)

Copyright 1987-2002, Larry Wall

Binary build 806 provided by ActiveState Corp. http://www.ActiveState.com
Built 00:45:44 Mar 31 2003
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top