2010-09-03 2 views
10

Perl 5.10 führte ein richtiges Switch-Konstrukt mit given/when ein und es scheint ein mächtiges Werkzeug zu sein.Welche sauberen Anwendungsfälle gibt es für gegeben/wann?

Gegenwärtig fehlen jedoch perldoc perlsyn einige gute Beispiele.

Ein Fall, in dem ich es praktisch, fand in letzter Zeit für war es mit Dateitest Operatoren:

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

oder alternativ:

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

Für mich, vor allem die erste Version sieht besser aus als eine if Konstruieren oder verwenden Sie den ternären Operator, wenn ich abhängig vom Ergebnis des Tests in beiden Fällen Aktionen ausführen muss.

Es hat mich jedoch wundern, was sonst sieht ordentlich aus jenseits des einfachen Falles zurück zu Smart-Matching und Vermeidung von überlangen If-elsif-elsif -...- sonst Strukturen?

Ich habe eine Ahnung, dass gegeben/wann es möglich ist, schlau zu sein, ohne an Klarheit zu verlieren, aber ich habe keine guten Beispiele.

Eine Sache, die mich aber überrascht, ist, dass man Nest das Konstrukt als gut:

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

Sie können '-f _', '-z _', '-d _' und '-o _' verwenden, um den Aufruf von' stat' zu vermeiden Die selbe Datei '-e' hat es angerufen. Weitere Informationen finden Sie unter ['perldoc -f -X'] (http://perldoc.perl.org/functions/-X.html). –

+0

In der Tat ist es normalerweise eine gute Idee, das zwischengespeicherte Formular zu verwenden. Ich wollte das Beispiel nicht mit nicht verwandten Dingen überkomplizieren. Es spielt sowieso selten eine Rolle für die Performance ... – szbalint

+0

'-d' umfasst' -e' und '-f' umfasst' -e', es gibt keinen Grund, '-e' zu ​​testen, außer'! -f &&! -d' , es würde nichts ändern, um nur anzunehmen, dass in diesem Fall, wenn "-e", dann ist es besonders. – Axeman

Antwort

3

In einem recent answer zu Zaids Frage Strategies to handle a file with multiple fixed formats, ich mit einem armen Mannes yacc dessen Hauptschleife durchsucht eine Reihe von am Ende reguläre Ausdrücke für das erste Spiel:

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

In einer anderen Frage, David B wanted to match against multiple regexes und my answer uses smart matching implizit Schleife über die reguläre Ausdrücke:

#! /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

Die 'gegebene' Anweisung ist ein wenig nervig. Gibt es einen Grund, warum 'while' nicht als Topicizer verwendet werden kann? –

2

nicht unter Sie wissen, ob ein ordentlich Use Case oder nur eine Spitze des Hutes zu Perl Sprach Linie ist :)

# 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 } 
} 

Und wenn Sie sehen $_ hat „es“ dann funktioniert es besonders gut (IMHO).

Die oben genannten Arbeiten von overloading das intelligente Spiel Betreiber, die given/when verlassen. Hier ist, wie TheTime Klasse geschrieben werden könnte, um meine Arbeit zu machen Beispiel:

{ 
    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. Siehe auch diesen Blogbeitrag, den ich vor kurzem gemacht habe: given/when – the Perl switch statement

+1

+1: nette Verwendung von 'Überlastung' – dawg

Verwandte Themen