Comment passer des paramètres optionnels à une fonction Perl?

je veux passer plusieurs paramètres, dont l'un est en option, à une fonction. La seule façon de le faire que je connaisse est d'utiliser une liste (@) comme paramètre. Ainsi, il ne contient rien ou 1 élément (ne sera jamais undef), de sorte que je peux utiliser le code suivant:

sub someFunction($$@) {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    ...
} 

ce code fonctionne, mais je pense que ce n'est peut-être pas la meilleure solution.

Existe-il d'autres façons de le faire?

Remercier.

16
demandé sur TLP 2011-11-14 19:48:51

3 réponses

Vous pouvez utiliser un point-virgule dans le prototype pour indiquer la fin de l'paramètres requis:

sub someFunction($$;$) {
  my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
  ...
}

; est optionnel avant un @ ou %, qui, selon la documentation, "gobe tout le reste".

EDIT: comme DVK le souligne dans un commentaire (et TLP le souligne dans une autre réponse ici), il est probablement préférable d'éviter simplement les prototypes:

sub someFunction {
  my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
  ...
}

les prototypes Perl ont leurs usages (essentiellement pour fournir des contexte coercition aux arguments, comme le font les fonctions intégrées de Perl). Ils doivent être utilisé comme un mécanisme pour vérifier que les fonctions sont appelées avec le nombre et le type d'arguments corrects.

18
répondu Ted Hopp 2015-01-28 16:26:56

Prototypes (($$@) partie de votre sous-déclaration) sont facultatifs eux-mêmes. Ils ont un usage très spécifique, et si vous ne savez pas ce que c'est, il est préférable de ne pas l'utiliser. De perlsub:

...le but de cette fonctionnalité est principalement pour vous permettre de définir des sous-routines qui fonctionnent comme des fonctions intégrées

il suffit de supprimer le prototype de votre sous-déclaration, et vous pouvez utiliser tous les arguments que vous voulez.

sub someFunction {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    if (defined $option_param) {
        # do optional things
    }
    $option_param //= "default optional value";
    ....
} 
36
répondu TLP 2011-11-14 16:15:49

C'est une bonne idée pour groupe de paramètres dans un $parameter hashref. Cela est particulièrement utile si plusieurs options (obligatoires ou facultatives) doivent être fournies.

pour accéder à n'importe quel paramètre, utilisez simplement $parameter->{oblig1} ou $$parameter{option2}.

passer des hashrefs le rend particulièrement pratique lors du développement, Donc quand le besoin de $oblig3 vient le long, l'ordre des arguments de changements ni l'appelant ni le sous elle-même. Comparer avant et après:


# BEFORE $oblig3

--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc( $oblig1,        | sub {
          $oblig2,        |   my ( $oblig1,
          $option1 );     |        $oblig2,
                          |        $option1 ) = @_;
                          | }
--------------------------+-------------------------

# AFTER $oblig3

--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc( $oblig1,        | sub {
          $oblig2,        |   my ( $oblig1,
          $oblig3,        |        $oblig2,
          $option1 );     |        $oblig3,
                          |        $option1 ) = @_;
                          | }
--------------------------+-------------------------

l'ordre des plaidoyers change à l'appelant et au sous-appelant, donc l'ordre doit être maintenu et respecté.

en utilisant des hashrefs, il n'y a pas besoin de s'inquiéter de l'ordre des arguments:

--------------------------+-------------------------
# Caller                  | # Sub
--------------------------+-------------------------
someFunc({ oblig1  => 1   | sub {
           oblig2  => 2   |   my ( $params ) = @_;
           option1 => 1   |   # No changes to    
           oblig3  => 7   |   # argument passing
         });              |  }    
                          | 
--------------------------+-------------------------

en fonction des besoins de conception du sous-programme, les patrons d'arguments du sous-programme suivants peuvent être utilisés:

  1. my ( $mandatory_parameters, $optional_parameters ) = @_;

    Ce modèle est utile si il y en a plusieurs chaque. La beauté de cette approche est qu' $optional_parameters n'est pas défini s'il n'est pas passé, donc le cas par défaut peut être exécuté if ! $optional_parameters;

    notez que les paramètres obligatoires devront être vérifiés par la suite:

    for ( qw/ a b c / ) { 
        die "Missing '$_' parameter\n"
          unless exists $mandatory_parameters->{$_};
    }
    
  2. my ( $parameters ) = @_;

    utile s'il y a peu ou pas de paramètres obligatoires.

    il est aussi extrêmement efficace si les paramètres sont passés à modifier simplement le comportement par défaut. Par définition $default_parameters dans la portée du paquet, les valeurs par défaut peuvent être chargées par une doublure subséquente à moins qu'un paramètre n'ait été explicitement passé:

    $parameters = { %$default_parameters, %$parameters };

14
répondu Zaid 2013-03-27 08:31:30