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

StackOverflow https://stackoverflow.com/questions/3112

  •  08-06-2019
  •  | 
  •  

Question

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

je veux faire un foreach boucle sur le tableau attendu.Sans vérifier ref($results) eq 'ARRAY', existe-t-il un moyen 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.

MODIFIER:Je dois préciser qu'il n'y a aucun moyen pour moi de modifier ce qui est renvoyé 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.

Était-ce utile?

La solution

je ne suis pas sûr qu'il existe un autre moyen que :

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

Autres conseils

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] );
    }
}

Vous pouvez alors toujours savoir que vous obtiendrez une référence à un tableau, même s’il ne s’agissait que d’un seul élément.

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

Eh bien, si vous ne pouvez pas le 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 et effrayant comme celui-ci !....

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

et pour éviter cette dangereuse évaluation de chaîne, cela devient vraiment moche !!....

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.

Je refactoriserais 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.

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, donc 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 pourrait être difficile à résoudre

Vous pouvez procéder ainsi :

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top