perl arrays reference scalar

¿Puedes forzar una referencia escalar o de matriz para que sea una matriz en Perl?



arrays reference (6)

Tengo un perl variable $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án en ese valor, y no una matriz referenciada que contenga ese elemento.

Quiero hacer un bucle foreach en la matriz esperada. Sin verificar ref($results) eq ''ARRAY'' , ¿hay alguna forma de tener algo equivalente a lo siguiente?

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

Esa muestra de código particular funcionará para la referencia, pero se quejará por el escalar simple.

EDITAR: Debería aclarar que no hay forma de que cambie lo que devuelve el servicio. El problema es que el valor será escalar cuando solo hay un valor y será una referencia de matriz cuando haya más de un valor.


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, ¿entonces estoy pensando que tiene algo que ver con el resultado obtenido del servicio? Si no tiene control sobre el servicio de devolución, esto podría ser difícil de descifrar


Bueno, si no puedes hacer ...

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 aterrador como este! ...

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

y para evitar esa evaluación de cadena peligrosa, se vuelve realmente feo !!

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

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


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

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


Otra solución sería envolver 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 se puede saber que obtendrá una referencia a una matriz, incluso si se trata de un solo elemento.

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


Puedes hacerlo así:

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


Volvería a factorizar el código dentro del ciclo y luego haré

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 ciclo no fuera trivial.