Am o variabilă perl $ results
care este returnată de la un serviciu. Valoarea ar trebui să fie o matrice și $ results
ar trebui să fie o referință de matrice. Cu toate acestea, atunci când matricea are un singur element în ea, $ results
va fi setat la acea valoare și nu o matrice de referință care conține acel element.
Vreau să fac o buclă foreach
pe matricea așteptată. Fără a verifica ref ($ results) eq 'ARRAY'
, există vreo modalitate de a avea ceva echivalent cu următoarele:
foreach my $result (@$results) {
# Process $result
}
Acest eșantion de cod special va funcționa pentru referință, dar se va plânge pentru scalarul simplu.
EDIT: Ar trebui să clarific faptul că nu există nicio modalitate de a schimba ceea ce este returnat din serviciu. Problema este că valoarea va fi scalară atunci când există o singură valoare și va fi o referință de matrice atunci când există mai mult de o valoare.
Tocmai am testat acest lucru cu:
#! / usr / bin / perl -w utilizați stricte; sub testit { my @ret = (); dacă (trecerea) { împinge @ ret, 1; împinge @ ret, 2; împinge @ ret, 3; } Else { împingeți @ret, "singură"; } returnați @ @ ret; } (@ {testit (1)}) { print $ r "test1 \ n"; } (@ {testit ()}) { print $ r "test2 \ n"; }
Și se pare că funcționează bine, deci mă gândesc că are ceva de-a face cu rezultatul obținut de la serviciu? Dacă nu aveți niciun control asupra serviciului de întoarcere, este posibil să fie greu să cedați
Aș re-factor cod în bucla și apoi face
if( ref $results eq 'ARRAY' ){
my_sub($result) for my $result (@$results);
}else{
my_sub($results);
}
Sigur că aș face asta doar dacă codul din buclă nu era banal.
O altă soluție ar fi să înfășurați apelul către server și să îl întoarceți întotdeauna o matrice pentru a simplifica restul vieții:
sub call_to_service
{
my $returnValue = service::call();
if (ref($returnValue) eq "ARRAY")
{
return($returnValue);
}
else
{
return( [$returnValue] );
}
}
Apoi, puteți ști mereu că veți primi o referință la o matrice, chiar dacă ar fi un singur element.
foreach my $item (@{call_to_service()})
{
...
}
Dacă nu puteți să ...
for my $result ( ref $results eq 'ARRAY' ? @$results : $results ) {
# Process result
}
sau asta...
for my $result ( ! ref $results ? $results : @$results ) {
# Process result
}
atunci ar fi posibil să încercați ceva înspăimântător ca acest lucru!
for my $result ( eval { @$results }, eval $results ) {
# Process result
}
și pentru a evita acest șir periculos eval devine foarte urât fugly! ....
for my $result ( eval { $results->[0] } || $results, eval { @$results[1 .. $#{ $results }] } ) {
# Process result
}
PS. Preferința mea ar fi să o abstracționez în sub ala call_to_service () exemplu dat de reatmon.