2009-02-20 8 views
6

En Perl, a menudo se puede evitar el uso de bloques de control, así:expresión foreach conciso en una línea

print "$_\n" foreach(@files); 

en lugar de:

foreach(@files){ 
    print "$_\n"; 
} 

¿Cómo funciona esto sintaxis en la siguiente, más caso complejo:

die("Not a file: $_") unless -f $_ foreach(@files); 

Me da un error de sintaxis. No estoy tratando de escribir código ofuscado, es solo una parte sin importancia en el programa, por lo que quiero expresarlo de la manera más concisa posible.

RESPUESTAS resumirse así:

que sólo puede aceptar una respuesta como la respuesta aceptada, pero me gusta los siguientes los de Chris y Jon mejor.

Ésta utiliza foreach como era mi intención, pero sin la syntax error:

-f or die "Not a file: $_" foreach @files; 

y el siguiente es al menos tan buena. Me gusta que die se encuentra al principio de la declaración, porque eso es lo que la atención del lector debe dirigirse a:

die("Not a file: $_") for grep {!-f} @files; 
+0

Estoy de acuerdo en que 'die()' es mejor al principio de la línea, pero en un apuro, la lógica de cortocircuito es igual de fácil de leer para mí. –

+1

¿Estás jugando al golf? De lo contrario, ¿por qué es importante tenerlo en una línea? –

Respuesta

12

sólo para estar Perlish (TMTOWTDI) se puede usar la lógica cortocircuitos:

-f or die "Not a file: $_" foreach @files; 

Probado en OS X y obras.

Como nota al margen, -f or die se parece a una gran cantidad de construcciones comunes open() or die que veo en Perl, y aún (I) que muestra la intención de la línea (a die bajo ciertas condiciones).

+1

Muy limpio. ++ y ¡hurra para la motosierra del ejército suizo! –

+0

Me gusta. El paralelo con open() o die() está un poco apagado, ya que el propósito de open() suele ser abrir un archivo que no se muera(). Pero si considera que el objetivo del código anterior es probar la existencia de un archivo, el paralelo es exacto. Llamada difícil, pero creo que me agrada un poco más la tuya. ;-) –

7

Bueno, no puede haber intención escribir código ofuscado, pero yo diría que 'Ciertamente tratando a.

¿Serían tan malas dos líneas (o incluso un bloque en una línea, como sugiere Brent.Longborough) en lugar de una? Honestamente, esta es la razón por la que generalmente odio intentar depurar/editar el código perl de otras personas, un gran número de personas que escriben en perl parecen estar obsesionadas con hacer casi todo de la manera más "inteligente" posible, en lugar de hacerlo de una manera que sea fácil de entender para otra persona leyendo.

+0

+1. Nunca entendí por qué "clevver == en una sola línea" para algunas personas. – innaM

+1

Creo que algunos de los ejemplos (como el que usa 'grep') son" inteligentes ", pero no porque sean solo una línea. Son inteligentes porque son solo una línea, pero muestran claramente el significado. Y se ve bien - paréntesis anidados y corchetes en una línea se ve mal (en mi opinión (excepto en Lisp (jaja))). –

3

Si no está tratando de escribir un código ofuscado, entonces no intente escribirlo así. Está tomando algo que debería ser simple y dificultar su comprensión.

+1

¿Qué demonios está ofuscado por esto? ¿Cómo lo escribirías? – Svante

+0

Estoy de acuerdo con Harleqin: varias respuestas en esta página muestran que hay formas de escribir esto que son a) claras yb) una línea. –

+0

Estaba respondiendo a su comentario diciendo "No estoy tratando de escribir código ofuscado". Su intento fue ofuscado como lo define Webster: "ser evasivo, poco claro o confuso". Las respuestas que se enviaron cuando publiqué no fueron claras y confusas, mientras que algunos ejemplos que se publicaron más tarde se ven bien. – gpojd

11

Usted podría utilizar @ respuesta de Brent.Longborough, o si realmente quiere postfix, hacer:

do { die("Not a file: $_") unless -f $_ } foreach(@files); 

Sin embargo, estoy de acuerdo con los otros, simplemente porque se trata de "una parte poco importante" no significa que conciso es mejor. La legibilidad cuenta.

+0

¿Cómo no es legible? ¿Cómo prefieres escribirlo? – Svante

+0

No dije que no era "legible". Sin embargo, afirmo que es * menos * legible utilizar estructuras de control de postfix encadenadas. Eso es por supuesto subjetivo. El punto es que el OP no dijo que estaba tratando de maximizar la legibilidad, sino que debería ser "conciso" porque era "sin importancia". –

5

Si la prueba de error es el punto principal de este código, podría tener sentido que tenga la ubicación principal al principio de la línea. Una ligera mejora sería utilizar grep:

die("Not a file: $_") for grep {!-f} @files; 

Pero si piensa en bucle a través de los archivos por alguna otra razón en esa parte del código, que sería mejor para agregarlo al cuerpo del bucle.

0

Maldita sea, Jon acaba de vencerme al grep.

Pero tengo una pregunta más importante: ¿cómo no es importante si realmente va a rescatar si encuentra algunos archivos que no son de su matriz? (A diferencia de, por ejemplo, eliminar esos elementos, advertir al usuario y luego procesar el resto de la lista.) Creo que matar a todo el shebang es una parte razonablemente importante del programa.

En cualquier caso, no puede hacer exactamente lo que quiere con los modificadores de postfix ya que solo puede tener una cosa en cada lado de ellos. Por lo tanto, no puede tener el unless y el foreach. Desde la parte superior del bit correspondiente de perldoc perlsyn:

Cualquier declaración simple opcionalmente puede estar seguido de un modificador SOLA, justo antes del punto y coma de terminación (o bloque final).

+0

Sí. Si fuera solo una impresión, diría que la notación tradicional es mejor. Pero probablemente sea la primera ficha en una línea, si es posible. –

1

Estás pensando demasiado. Aquí está en una línea sin acrobacias:

foreach (@files) { die("Not a file!") unless -f } 

Es posible jugar con las cosas dentro del bloque al golf hacia abajo, pero la eliminación de los parens y los apoyos no le está ayudando a cualquiera, y es probablemente va confundir al próximo programador que tiene que mirarlo.

Sin embargo, probablemente tenga algo más complicado, y esto es solo un ejemplo. En el mundo real, es incluso más fácil:

not_a_file_die_die_die(\@files); 

Luego mueve todo el material complicado a una subrutina. El verdadero truco es hacer que la idea y intent sea concisa, no el código que implementa la idea. La mecánica realmente no importa en muchos casos; te importa más el resultado En esos casos, no te preocupes por la mecánica.

Cuestiones relacionadas