Wo finde ich in Perl eine switch()-Funktion?

Inhalt:

Du vermisst die switch()-Funktion, die du aus C oder Basic kennst?

Du kommst von einer anderen Programmiersprache wie Basic oder C und vermisst die switch-Funktion? Leider gibt es die in Perl nicht. Da jedoch Perl eine so mächtige Sprache ist, kann man es sich selbst auf verschiedene Arten bauen. Einige Hinweise dazu findest du auch in der Perl-Dokumentation mit
        perldoc -q switch
        

Der neue Weg

Seit Perl 5.10.0 gibt es ein neues Konstrukt, das mehr ist als das switch aus anderen Sprachen. In Perl 5.10 heißt das Konstrukt "given/when". Um die Kompatibilität zu früheren Perl-Versionen aufrecht zu halten, muss man dieses neue Feature extra einschalten. Entweder über

  use 5.010;

oder mit

  use feature 'switch';

Danach kann man "given/when" verwenden:

#!/usr/bin/perl

#use 5.010;
use feature 'switch';

my $c = 't';
given( $c ) {
    when( 't' ){ 
        print "t";
    };
    when( 1 ){
        print "1";
    };
}

Das sieht jetzt nicht so aus, als könnte es mehr als andere Sprachen, aber der Clou liegt in den Vergleichen bei "when". Dort wird der sogenannte SmartMatch?-Operator verwendet. Damit kann man z.B. überprüfen, ob ein Element in einem Array vorhanden ist - und noch viel mehr.

#!/usr/bin/perl

#use 5.010;
use feature 'switch';

my $c = 't';
my @array = qw(a b c t);

given( $c ) {
    when( @array ){ 
        print "yes";
    };
}

Der klassische Weg

          SWITCH:
          {
            if ($key == 1) { &Sub1($key,10); last SWITCH; }
            if ($key == 2) { &Sub2($key,10); last SWITCH; }
            if ($key == 3) { &Sub3($key,10); last SWITCH; }
          }
          

Mit Hash von Referenzen auf Subs

   # Vorbereiten der Verweise auf die Subs:
   my %switch = (
      1 => \&Sub1,
      2 => \&Sub2,
      3 => \&Sub3,
   );

   # Überprüfen, ob Verweis auf Funktion definiert
   if (exists $switch{$key} ) {
      # Wenn ja, dann die Funktion ausführen und dabei eventuell
      # Parameter übergeben (hier: 1,2,3)
   $switch{$key}->(1,2,3); # Pfeil-Schreibweise
        } else {
      # Wenn nein, dann einen Fehler ausgeben. Man könnte hier z.B. auch
      # auf eine Standardfunktion (=Default) umleiten.
      print "Fehler: Element nicht vorhanden\n";
   }

   # oder mit anderer Schreibweise:
   if (exists $switch{$key}){
      &{ $switch{$key} }(4,5,6); # explizite dereferenzierung
   } else {
      print "Fehler: Element nicht vorhanden\n";
   }
        

Evaluierung zur LaufZeit?

   %switch = (
           1 => "Sub1('hallo')",
           2 => "Sub2()",
           3 => "Sub3('irgendwelche Parameter')",
   );

   if (exists $switch{$key} ) {
      eval $switch{$key};
   } else {
      print "Fehler: Element nicht vorhanden\n";
   }
   

Evaluierung zur CompileZeit?

Bei den folgenden Beispielen wird nicht eine der Funktionen on-the-fly ausgeführt, sondern es wird jede Funktion ausgeführt, und es wird mit den Rückgabewerten gearbeitet. Eine solche Art von Switch genügt in den folgenden Fällen:

  1. Die Parameter für die Funktion sind schon bekannt, wenn der Hash gebaut wird.
  2. Die Funktionen machen selbst keinen Input/Output, sondern liefern nur etwas (z.B. das Ergebnis einer Berechnung) zurück. Denn es werden alle Funktionen ausgeführt, und der Switch geht nur auf die Rückgabewerte der Funktionen.
  3. Die Funktionen laufen recht kurz. Falls sie eine längere Laufzeit benötigen sollten, ist wohl eher aus Effizienzgründen eine der Lösungen von oben angebracht.

Im ersten Beispiel werden alle zu berechnenden Werte beim Aufbau des Hashes %switch berechnet:
   my %switch = (
      1 => &x1(1,3),
      2 => &x2(2,3),
      3 => &x3(3,3),
   );

   my $key = 1 ;
   print $switch{$key}."\n";
   

Im zweiten Beispiel wird der Wert erst berechnet, wenn dieser tatsächlich benötigt wird (VerzögerteAuswertung):
   my %switch = ( # backslashes hinzugefuegt (StraT)
           1 => \&x1,
           2 => \&x2,
           3 => \&x3
        );

   my $key = 3 ;
   print &{$switch{$key}}(9,9)."\n";
   # oder: print $switch{$key}->(9,9), "\n"; # (StraT)

   sub x1 { $_[0] * $_[1]; }
   sub x2 { $_[0] * $_[1]; }
   sub x3 { $_[0] * $_[1]; }
   

Ausnutzung der KurzSchlussF?ähigkeit von Perl

   my $name = "hase";

   $name eq "hund" and do { print $name } or
   $name eq "katz" and do { print $name . "!" } or
   $name eq "hase" and do { print $name . "!!" };
   

Das Switch Modul

Das Switch Modul ist eine Implementierung des switch Statements auf SourceFilter? Basis. Seit Perl 5.8.0 ist es ein StandardModul.

   use Switch;

   my $val = rand (100);
   switch ($val) {
      case 1 { print "number 1" }
      case "a" { print "string a" }
      case [1..10,42] { print "number in list" }
      case (@array) { print "number in list" }
      case /\w+/ { print "pattern" }
      case qr/\w+/ { print "pattern" }
      case (%hash) { print "entry in hash" }
      case (\%hash) { print "entry in hash" }
      case (\&sub){ print "arg to subroutine" }
      else { print "previous case not true" }
   }
   

Exkurs: Die C Implementierung

Die Sprache C enthält - anders als Perl - bereits ein Statement switch.

   #include <stdlib.h>
   #include <stdio.h>

   int main() {
      int i=1;

      switch(i) {
         case 1: { Sub1("Hallo"); break; }
         case 2: { Sub2(); break; }
         case 3: { Sub3(); break; }
      }

      return 0;
   }

   char Sub1(char str) { return str; }
   int Sub2() { printf("sub2\n"); }
   int Sub3() { printf("sub3\n"); }
   

-- TinaMueller, StefanHanke, HaraldBongartz - 15 Aug 2003

UtilFaqSubForm edit

Titel Wo finde ich in Perl eine switch()-Funktion?
Autor wozki, ich & perl-community, diku, syndrom, strat
Bereich FaqSchleifen
Tags
Topic revision: 2009-02-05, ReneeBaecker
 
Bitte die NutzungsBedingungen beachten.
Bei Vorschlägen, Anfragen oder Problemen mit dem PerlCommunityWiki bitten wir um WebBottomBarExample">Rückmeldung.