Pregunta

tengo una variable perl $results que se devuelve de un servicio.Se supone que el valor es una matriz, y $results debe ser una referencia de matriz.Sin embargo, cuando la matriz tiene solo un elemento, $results se establecerá en ese valor, y no en una matriz referenciada que contenga ese elemento.

quiero hacer un foreach bucle en la matriz esperada.sin comprobar ref($results) eq 'ARRAY', ¿hay alguna manera de tener algo equivalente a lo siguiente?

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

Ese ejemplo de código en particular funcionará para la referencia, pero se quejará para el escalar simple.

EDITAR:Debo aclarar que no tengo forma de cambiar lo que se devuelve del servicio.El problema es que el valor será escalar cuando solo haya un valor y será una referencia de matriz cuando haya más de un valor.

¿Fue útil?

Solución

No estoy seguro de que haya otra forma que no sea:

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

Otros consejos

Otra solución sería ajustar la llamada al servidor y hacer que siempre devuelva una matriz para simplificar el resto de su vida:

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

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

Entonces siempre podrás saber que obtendrás una referencia a una matriz, incluso si fuera solo un elemento.

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

Bueno, si no puedes hacerlo...

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

o esto...

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

¡Entonces quizás tengas que probar algo tan aterrador como esto!...

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

y para evitar esa peligrosa cadena de evaluación se vuelve realmente fea!!....

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

PD.Mi preferencia sería abstraerlo en el ejemplo sub ala call_to_service() proporcionado por reatmon.

Refactorizaría el código dentro del bucle y luego haría

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

Por supuesto, solo haría eso si el código en el bucle no fuera trivial.

Acabo de probar esto con:

#!/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";
}

Y parece funcionar bien, así que creo que tiene algo que ver con el resultado obtenido del servicio.Si no tienes control sobre el servicio que regresa, esto podría ser difícil de descifrar.

Puedes hacerlo así:

my @some_array
push (@some_array, results);
foreach my $elt(@some_array){
  #do something
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top