Reputation: 15987
I want to return an empty array, not an empty list.
I have a sub that returns an array of things. I want to be able to do this with it:
my $count = scalar getArray();
I did it like this:
sub getArray {
if ( !isGood() ) {
return ();
} else {
my @array = calculateSomehow();
return @array;
}
}
my $count = scalar getArray();
I had a suprise when !isGood()
and $count
becomes undef
, not 0
! After reading perlfaq4, I realize that this is because getArray() is evaluated in scalar context and hence the list ()
is evaluated as a scalar, and scalar( () )
is undef
, while my @array; scalar( @array )
is 0.
The question now becomes: How do I most elegantly return an empty array, so that $count
is 0
if !isGood()
? I've only come up with:
# This is kind of kludgy: Dereference an anonymous array ref. Really?
return @{[]};
or
# I use a temporary variable for this. Really?
my @empty;
return @empty;
Aren't there any cleaner / more elegant ways of returning an array of length 0 (empty array) or some other way of making scalar getArray()
evaluate to 0
?
Upvotes: 3
Views: 4235
Reputation: 66964
A subroutine can only return a list (of scalars) in Perl.
If an array variable is given to return
it is evaluated and either a list of its elements is returned, if the sub is called in a list context, or its length (number of elements), if the sub is called in a scalar context. (Originally stated in comments, only summarized here in this edit.)
The closest to "returning an array" is to return a reference to it.
Return a reference and you can get the array size (0 if empty) in one call, by dereferencing.
sub getArray {
# calculate ...
return \@results; # @results may be empty ( or [@results] )
}
$rres = getArray();
my $count = @$rres; # gives 0 if ref is to empty array
my $cnt = @{ getArray() }; # or without storing the return
You can use scalar
above, if you wish, but you don't need to. This is also alike to returning a pointer to an array (even if empty), if that's what you had in mind by requiring an "empty array."
If you want to go this route but to single out the not-good
sub getArray {
return if !isGood(); # returns undef
# calculate ...
return \@results; # scalar whether the list be empty or not
}
Using context may help -- either get your list from the array (empty or not), or 0
for a scalar
sub getArray {
if (!isGood() ) {
return (wantarray) ? () : 0;
}
else { } # your code
}
my @results = getArray() # returns a list, possibly empty
my $count = getArray(); # returns 0
Upvotes: 2
Reputation: 29790
It's probably clearest if you just return an array in both cases:
sub getArray {
my @array;
@array = calculateSomehow() if isGood();
return @array;
}
But to modify your original code in the minimal way, use wantarray
.
if (!isGood()) {
return wantarray ? () : 0;
}
Upvotes: 7