web-dev-qa-db-fra.com

Obtenir un comportement switch/case en Perl 5

Existe-t-il un moyen intéressant de faire une déclaration de cas ou d’aiguillage dans Perl 5 ?. Il me semble qu'ils devraient inclure un commutateur sur la version 6 ..

J'ai besoin de cette structure de contrôle dans un script, et j'ai entendu dire que vous pouvez importer un "module de commutation". Mais comment puis-je y parvenir sans importer pour minimiser les dépendances et acquérir la portabilité?

27
lurks

Si vous utilisez Perl 5.10, vous avez given/when qui est une instruction switch (remarque: vous pouvez faire plus que comparer avec des expressions rationnelles, lisez les documents liés pour voir tout son potentiel):

#or any of the dozen other ways to tell 5.10 to use its new features
use feature qw/switch/; 

given($string) {
    when (/^abc/) { $abc     = 1; }
    when (/^def/) { $def     = 1; }
    when (/^xyz/) { $xyz     = 1; }
    default       { $nothing = 1; }
}

Si vous utilisez Perl 5.8 ou une version antérieure, vous devez utiliser les instructions if/elsif/else:

if    ($string =~ /^abc/) { $abc     = 1; }
elsif ($string =~ /^def/) { $def     = 1; }
elsif ($string =~ /^zyz/) { $xyz     = 1; }
else                      { $nothing = 1; }

ou imbriqués opérateurs de condition (?:) :

$string =~ /^abc/ ? $abc     = 1  :
$string =~ /^def/ ? $def     = 1  :
$string =~ /^xyz/ ? $xyz     = 1  :
                    $nothing = 1;

Il y a un module dans Core Perl ( Switch ) qui vous donne de fausses instructions de switch via filtres source , mais je crois comprendre qu'il est fragile :

use Switch;

switch ($string) {
    case /^abc/ {
    case /^abc/ { $abc     = 1 }
    case /^def/ { $def     = 1 }
    case /^xyz/ { $xyz     = 1 } 
    else        { $nothing = 1 }
}

ou la syntaxe alternative

use Switch 'Perl6';

given ($string) {  
    when /^abc/ { $abc     = 1; }
    when /^def/ { $def     = 1; }
    when /^xyz/ { $xyz     = 1; }
    default     { $nothing = 1; }
}
57
Chas. Owens

La suggestion dans Programmation Perl est la suivante:


for ($string) {
    /abc/ and do {$abc    = 1; last;};
    /def/ and do {$def    = 1; last;};
    /xyz/ and do {$xyz    = 1; last;};
    $nothing = 1;
}
17
Nathan Fellman

Juste un bref commentaire sur le module principal commutateur qui a été mentionné à quelques reprises dans les réponses. Le module en question s'appuie sur des filtres source. Entre autres choses, cela peut entraîner des lignes erronées signalées pour des erreurs. C'est tellement grave qu'aucun des développeurs principaux ne se souvient vraiment de la raison pour laquelle il a été accepté dans le noyau Perl.

En outre, Switch.pm sera le premier module Perl à être supprimé du noyau Perl. La prochaine version majeure de Perl, la 5.12.0, l’aura toujours, bien qu’un avertissement de dépréciation soit émis. Cet avertissement de désapprobation disparaîtra si vous installez explicitement Switch.pm à partir de CPAN. (Vous obtenez ce que vous demandez.) Dans la prochaine version, 5.14, Switch.pm sera entièrement supprimé du noyau.

9
tsee

Une solution équivalente que j'aime bien est un dispatch table .

my $switch = {
  'case1' => sub { print "case1"; },
  'case2' => sub { print "case2"; },
  'default' => sub { print "unrecognized"; }
};
$switch->{$case} ? $switch->{$case}->() : $switch->{'default'}->();
8
jiggy
print("OK : 1 - CANCEL : 2\n");
my $value = <STDIN>;
SWITCH: {
    ($value == 1) && last(SWITCH);
    ($value == 2) && do {print("Cancelled\n"); exit()};
    print("??\n");
}
0
Weeble