Using scalar() on function return values

J

J. Romano

Hi,

I am posting this message because I am a little confused on what
the scalar() function returns when called with functions that return
lists and/or arrays.

I know that calling scalar() on a list returns the last element of
a list, and that calling scalar() on an array returns the number of
elements in the array, but what if scalar() is called on a list that
ends with an array?

To clarify, consider the following code:


#!/usr/bin/perl -w
use strict;

# f1() returns a list
sub f1
{
return ('red', 'green', 'blue', 'yellow');
}

# f2() returns an array
sub f2
{
my @array = ('cat', 'dog', 'bird');
return @array;
}

# f3() returns a list with an array
sub f3
{
my @array = ('cat', 'dog', 'bird');
return ('red', 'green', 'blue', 'yellow', @array);
}


print "f1() returns ", scalar( f1() ), "\n";
print "f2() returns ", scalar( f2() ), "\n";
print "f3() returns ", scalar( f3() ), "\n";

__END__


It's easy to see that scalar( f1() ) returns "yellow" (the last
element of the list), and that scalar( f2() ) returns 3 (the number of
elements in its array. But what does scalar( f3() ) return?

You might think it either returns "bird" (the last element of the
array) or 7 (the number of elements in the list), but it returns
neither. In fact, it returns 3, apparently the number of elements in
the @array. This seems odd to me because it looks like that the
scalar() call is being called twice: Once to single out the @array,
and the next time to count the number of elements in the @array.

Does this sound logical, or is what I'm doing considered bad coding
practice and should never be used? If someone can clarify why what
I'm getting is logical, that would be appreciated.

-- Jean-Luc
 
R

Randal L. Schwartz

J> I am posting this message because I am a little confused on what
J> the scalar() function returns when called with functions that return
J> lists and/or arrays.

If you use scalar, it's *not* returning a list or array. It's
returning a scalar. The last expression evaluated in the subroutine
is evaluated in scalar context in this case.

print "Just another Perl hacker,"; # the original
 
G

Gunnar Hjalmarsson

J. Romano said:
sub f3
{
my @array = ('cat', 'dog', 'bird');
return ('red', 'green', 'blue', 'yellow', @array);
}

what does scalar( f3() ) return?

You might think it either returns "bird" (the last element of the
array) or 7 (the number of elements in the list), but it returns
neither. In fact, it returns 3, apparently the number of elements
in the @array.

If someone can clarify why what I'm getting is logical, that would
be appreciated.

Here is an attempt:

From "perldoc perlsub":
"The return value of a subroutine is the value of the last expression
evaluated. More explicitly, a return statement may be used to exit the
subroutine, optionally specifying the returned value, which will be
evaluated in the appropriate context (list, scalar, or void) depending
on the context of the subroutine call."

Accordingly, your observation is not related to the subroutine, but
this gives a similar result (together with a bunch of warnings):

my @array = qw(cat dog bird);
print scalar ('red', 'green', 'blue', 'yellow', @array);

From "perldoc perldata":
"LISTs do automatic interpolation of sublists. That is, when a LIST is
evaluated, each element of the list is evaluated in list context, and
the resulting list value is interpolated into LIST just as if each
individual element were a member of LIST."

That is true when a LIST is evaluated in list context but, as your
example illustrates, not when it is evaluated in scalar context.
 
J

Joe Smith

J. Romano said:
But what does scalar( f3() ) return?

In list context, f3's return() is in list context, and returns a list.
In scalar context, f3's return() is evaluated in scalar context, which
means that each of its arguments is evaluated in scalar context individually.

return scalar('red', 'green', 'blue', @array);
is the same as
return (scalar('red'), scalar('green'), scalar('blue'), scalar(@array));
which in this case is
return (scalar('red'), scalar('green'), scalar('blue'), 3);

-Joe
 
J

J. Romano

Joe Smith said:
return scalar('red', 'green', 'blue', @array);
is the same as
return (scalar('red'), scalar('green'), scalar('blue'), scalar(@array));
which in this case is
return (scalar('red'), scalar('green'), scalar('blue'), 3);

Thanks. That explains it well (you're the first to explain it to me that way).

Thank-you for all your responses.

-- Jean-Luc
 

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,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top