2011-09-07 12 views
9

Sin conocer realmente a Perl, he mejorado un script de Perl con la ayuda de un motor de búsqueda amigable.¿Hay una manera más limpia de "durar" condicionalmente este bucle de Perl?

Me parece que necesito para salir de un bucle while establecer un indicador si una condición se cumple:

foreach my $element (@array) { 
    if($costlyCondition) { 
     $flag = 1; 
     last; 
    } 
} 

sé que la manera más agradable de utilizar 'última' es algo como esto:

foreach my $element (@array) { 
    last if ($costlyCondition); 
} 

Por supuesto, esto significa que si bien puedo disfrutar el azúcar sintáctico, no puedo establecer mi bandera dentro del ciclo, lo que significa que necesito evaluar $costlyCondition una vez más afuera.

¿Hay alguna manera más clara de hacerlo?

+6

postfix 'if' en realidad solo es para una afirmación. El primero es preferible para múltiples declaraciones en un condicional. –

+0

Creo que un bloque if es la mejor opción en este caso. El argumento habitual para los condicionales de postfix en los controles de bucle es que coloca el código más significativo a la izquierda. Haciendo hincapié en que el ciclo tiene múltiples condiciones de salida sobre cuáles son esas condiciones de salida. En este caso, si usa algunas de las expresiones compuestas sugeridas, el resultado entierra el control de bucle más profundo en la expresión, lo que hace que sea más difícil verlo de un vistazo. –

+0

@Joel: tienes razón. Me quedo con la versión original. – ArjunShankar

Respuesta

21

puede utilizar un bloque do {...}:

do {$flag = 1; last} if $costlyCondition 

puede utilizar el operador , para unirse a las declaraciones:

$flag = 1, last if $costlyCondition; 

puede hacer lo mismo con la lógica && operador:

(($flag = 1) && last) if $costlyCondition; 

o incluso la prioridad más baja and:

(($flag = 1) and last) if $costlyCondition; 

al final del día, no hay ninguna razón real para hacer cualquiera de estos. Todos hacen exactamente lo mismo que tu código original. Si su código original funciona y es legible, déjelo como está.

+0

Agrega '$ flag = 1 y last if $ costlyCondition;' a tu tool-shelf. –

+0

en su segundo ejemplo, suelte {}. No son necesarios. – ysth

+0

¡Aprendo una nueva construcción perl! (hacer). ¡Gracias! Y como usted y casi todos dijeron, es mejor mantener el código tal como está. – ArjunShankar

5

Una idea es hacer el ciclo en una subrutina que devuelve valores diferentes dependiendo del punto de salida.

my $flag = check_elements(\@array); 

# later... 

sub check_elements { 
    my $arrayref = shift; 
    for my $ele (@$arrayref) { 
    return 1 if $costly_condition; 
    } 
    return 0; 
} 
7

Estoy de acuerdo con Nathan, que aunque el código de aspecto limpio es limpio, a veces una versión legible es mejor. Sólo por el placer de hacerlo, sin embargo, aquí está una versión terrible:

last if $flag = $costly_condition; 

Nota el uso de la asignación = en lugar de la igualdad ==. La asignación devolverá cualquier valor que esté en $costly_condition.

Esto, por supuesto, no hará $flag = 1, pero cualquiera que sea $costly_condition es. Pero, como eso debe ser cierto, también lo será $flag. Para remediar esto, se puede - como se menciona en el Zaid comentarios - utilización:

last if $flag = !! $costly_condition; 

Como se mencionó, las soluciones bastante horrible, pero que hacen el trabajo.

+4

'last if $ flag = !! $ costly_condition; 'haría el truco;) – Zaid

+0

@zaid Hehe, sí, también vi eso. – TLP

+0

para hacerlo aún peor: 'last unless $ flag =! $ costly_condition';) – pavel

0

Esto es posible, pero muy recomendable: tales trucos disminuyen la legibilidad de su código.

foreach my $element (@array) { 
    $flag = 1 and last if $costlyCondition; 
} 
Cuestiones relacionadas