2010-09-03 12 views
10

Perl 5.10 introdujo una construcción de interruptor adecuada con given/when y parece una herramienta poderosa. Sin embargo, actualmente perldoc perlsyn carece de algunos buenos ejemplos.¿Qué tipo de casos de uso aseados existen para/cuándo?

un caso en el que encontré a mano últimamente era para usarlo con los operadores de la prueba del archivo:

given (-d "foo/bar/") { 
    when (1) { ... } # defined is wrong as -d returns '' on a file. 
    default { ... } 
} 

o alternativamente:

given ("foo/bar/") { 
    when (-d) { ... } 
    default { ... } 
} 

Para mí, sobre todo la primera versión se ve mejor que un if - si construyo o uso el operador ternario, cuando dependa del resultado de la prueba, necesito realizar acciones en ambos casos.

Me hizo preguntarme, ¿qué otra cosa se ve bien más allá del simple caso de caer de nuevo a la coincidencia inteligente y evitar demasiado si-elsif-elsif -...- otras estructuras?

Tengo la corazonada de que, dado/cuando, es posible ser inteligente sin perder la claridad, pero no tengo ningún buen ejemplo.

Una cosa que me sorprendió, sin embargo, es que puede anidar la también de construcción:

given ($filename) { 
     when (-e) { 
       when (-f) { 
         when (-z) { say "Empty file" } 
         default { say "Nonempty file" } 
       } 
       when (-d) { 
         when (-o) { say "Directory owned by me"} 
         default { say "Directory owned by someone else" } 
       } 
       default { say "Special" } 
     } 
     default { say "No such file or directory" } } 
+1

Puede usar '-f _',' -z _', '-d _' y' -o _' para evitar llamar 'stat' al el mismo archivo '-e' lo llamó. Ver ['perldoc -f -X'] (http://perldoc.perl.org/functions/-X.html) para más información. –

+0

De hecho, generalmente es una buena idea usar el formulario en caché. Sin embargo, no quería complicar demasiado el ejemplo con cosas no relacionadas. Rara vez importa para el rendimiento de todos modos ... – szbalint

+0

'-d' abarca' -e' y '-f' abarca' -e', no hay ninguna razón para probar '-e' a menos que'! -f &&! -d' , no cambiaría nada el solo asumir que en ese caso, si '-e', entonces es especial. – Axeman

Respuesta

3

En un recent answer a la pregunta de Zaid Strategies to handle a file with multiple fixed formats, que terminó con yacc de un pobre hombre cuyo bucle principal buscado una serie de expresiones regulares para el primer partido:

while (<>) { 
    given($_) { 
    when (@{[ map $pattern{$_}, @expect ]}) {} 
    default { 
     die "$0: line $.: expected " . join("|" => @expect) . "; got\n$_"; 
    } 
    } 
} 

En otra pregunta, David B wanted to match against multiple regexes y my answer uses smart matching de forma implícita bucle sobre las expresiones regulares:

#! /usr/bin/perl 

use warnings; 
use strict; 

use feature 'switch'; 

my @patterns = (
    qr/foo/, 
    qr/bar/, 
    qr/baz/, 
); 

for (qw/ blurfl bar quux foo baz /) { 
    print "$_: "; 
    given ($_) { 
    when (@patterns) { 
     print "hit!\n"; 
    } 
    default { 
     print "miss.\n"; 
    } 
    } 
} 
+2

La declaración 'given' es un poco molesta. ¿Hay alguna razón por la cual 'while' no se pueda usar como tópico? –

2

No sé si a continuación es un caso utilización ordenada o simplemente un consejo de los ojos al linaje lingüística de Perl :)

# things todo (or should have done!) at this time of the day: 

given (TheTime->of_day) { 

    when ('morning') { 
     breakfast(); 
     make_packed_lunch() if $_->is_work_day; 
    } 

    lunch() when 'afternoon'; 

    when ('evening') { 
     goto_pub() if $_->is_friday; 
     dinner(); 
    } 

    default { say "Should be sleeping if its " . $_->{dt}->ymd } 
} 

Y si ve $_ tiene "que" entonces funciona particularmente bien (en mi humilde opinión).

Lo anterior funciona por overloading el operador de coincidencia inteligente que se basa en given/when. Aquí es cómo TheTime clase se podría escribir para hacer mi trabajo ejemplo:

{ 
    package TheTime; 
    use DateTime; 
    use overload '~~' => '_check_hour', fallback => 1; 

    our %day_time = (
     morning => [0..11], 
     afternoon => [12..17], 
     evening => [18..23], 
    ); 

    sub of_day { 
     my $class = shift; 
     bless { 
      dt => DateTime->now, 
     }, $class; 
    } 

    sub is_work_day { shift->{dt}->day_of_week ~~ [1..5] } 
    sub is_friday { shift->{dt}->day_of_week == 5  } 

    sub _check_hour { 
     my ($self, $greeting) = @_; 
     $self->{dt}->hour ~~ $day_time{$greeting}; 
    } 
} 

/I3az/

PS. También vea esta publicación en el blog que hice recientemente: given/when – the Perl switch statement

+1

+1: buen uso de 'sobrecarga' – dawg