Can you force either a scalar or array ref to be an array in Perl?

13,958

Solution 1

im not sure there's any other way than:

$result = [ $result ]   if ref($result) ne 'ARRAY';  
foreach .....

Solution 2

Another solution would be to wrap the call to the server and have it always return an array to simplify the rest of your life:

sub call_to_service
{
    my $returnValue = service::call();

    if (ref($returnValue) eq "ARRAY")
    {
        return($returnValue);
    }
    else
    {
       return( [$returnValue] );
    }
}

Then you can always know that you will get back a reference to an array, even if it was only one item.

foreach my $item (@{call_to_service()})
{
  ...
}

Solution 3

Well if you can't do...

for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
    # Process result
}

or this...

for my $result ( ! ref $results ? $results : @$results ) {
    # Process result
}

then you might have to try something hairy scary like this!....

for my $result ( eval { @$results }, eval $results ) {
    # Process result
}

and to avoid that dangerous string eval it becomes really ugly fugly!!....

for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
    # Process result
}

PS. My preference would be to abstract it away in sub ala call_to_service() example given by reatmon.

Share:
13,958
Rudd Zwolinski
Author by

Rudd Zwolinski

Updated on June 18, 2022

Comments

  • Rudd Zwolinski
    Rudd Zwolinski almost 2 years

    I have a perl variable $results that gets returned from a service. The value is supposed to be an array, and $results should be an array reference. However, when the array has only one item in it, $results will be set to that value, and not a referenced array that contains that one item.

    I want to do a foreach loop on the expected array. Without checking ref($results) eq 'ARRAY', is there any way to have something equivalent to the following:

    foreach my $result (@$results) {
        # Process $result
    }
    

    That particular code sample will work for the reference, but will complain for the simple scalar.

    EDIT: I should clarify that there is no way for me to change what is returned from the service. The problem is that the value will be a scalar when there is only one value and it will be an array reference when there is more than one value.