Pouvez-vous forcer un scalaire ou une référence de tableau à être un tableau en Perl?

Translate

J'ai une variable perl$resultsqui est renvoyé d'un service. La valeur est censée être un tableau, et$resultsdoit être une référence de tableau. Cependant, lorsque le tableau ne contient qu'un seul élément,$resultssera défini sur cette valeur, et non sur un tableau référencé contenant cet élément.

Je veux faire unforeachboucle sur le tableau attendu. Sans vérifierref($results) eq 'ARRAY', est-il possible d'avoir quelque chose d'équivalent à ce qui suit:

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

Cet exemple de code particulier fonctionnera pour la référence, mais se plaindra du simple scalaire.

EDIT: Je dois préciser qu'il n'y a aucun moyen pour moi de changer ce qui est retourné par le service. Le problème est que la valeur sera un scalaire lorsqu'il n'y a qu'une seule valeur et ce sera une référence de tableau lorsqu'il y a plus d'une valeur.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Je ne suis pas sûr qu'il y ait un autre moyen que:

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

Une autre solution serait d'encapsuler l'appel au serveur et de lui faire toujours renvoyer un tableau pour simplifier le reste de votre vie:

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

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

Ensuite, vous pouvez toujours savoir que vous récupérerez une référence à un tableau, même s'il ne s'agissait que d'un élément.

foreach my $item (@{call_to_service()})
{
  ...
}
La source
Translate

Eh bien, si vous ne pouvez pas faire ...

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

ou ca...

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

alors vous devrez peut-être essayer quelque chose de poilu effrayant comme celui-ci! ....

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

et pour éviter cette dangereuse eval string ça devient vraiment moche fugly !! ....

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

PS. Ma préférence serait de l'abstraire dans l'exemple sub ala call_to_service () donné par reatmon.

La source
Translate

Je re-factoriserais le code à l'intérieur de la boucle, puis je ferais

if( ref $results eq 'ARRAY' ){
    my_sub($result) for my $result (@$results);
}else{
    my_sub($results);
}

Bien sûr, je ne le ferais que si le code de la boucle n'était pas trivial.

La source
Translate

Je viens de tester ça avec:

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

sub testit {

 my @ret = ();
 if (shift){
   push @ret,1;
   push @ret,2;
   push @ret,3;
}else{
  push @ret,"oneonly";
}

return \@ret;
}

foreach my $r (@{testit(1)}){
  print $r." test1\n";
}
foreach my $r (@{testit()}){
   print $r." test2\n";
}

Et cela semble fonctionner correctement, alors je pense que cela a quelque chose à voir avec le résultat renvoyé par le service? Si vous n'avez aucun contrôle sur le service de retour, cela peut être difficile à craquer

La source
Fitch Lee
Translate

Vous pouvez le faire comme ceci:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
La source