parametros - perl $argv
¿Cómo pasar parámetros opcionales a una función de Perl? (3)
Quiero pasar varios parámetros, uno de los cuales es opcional, a una función. La única forma de hacerlo que conozco es usando una lista (@) como parámetro. Por lo tanto, no contiene nada o 1 elemento (nunca será undef), por lo que puedo usar el siguiente código:
sub someFunction($$@) {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
Este código funciona, pero creo que tal vez no sea la mejor solución.
¿Hay alguna otra forma de hacerlo?
Gracias.
Es una buena idea agrupar los parámetros en un hashref de $parameter
. Esto es especialmente útil si se deben proporcionar varias opciones (obligatorias u opcionales).
Para acceder a cualquier parámetro, simplemente use $parameter->{oblig1}
o $$parameter{option2}
.
El paso de hashrefs lo hace especialmente conveniente cuando se desarrolla, por lo que cuando surge la necesidad de $oblig3
, el orden de los argumentos no cambia ni en la persona que llama ni en el subdominio. Comparar antes y despué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 ) = @_;
| }
--------------------------+-------------------------
El orden de los argumentos cambia tanto en la persona que llama como en el usuario secundario, por lo que el orden debe mantenerse y respetarse.
Usando hashrefs, no hay necesidad de preocuparse por el orden de los argumentos:
--------------------------+-------------------------
# Caller | # Sub
--------------------------+-------------------------
someFunc({ oblig1 => 1 | sub {
oblig2 => 2 | my ( $params ) = @_;
option1 => 1 | # No changes to
oblig3 => 7 | # argument passing
}); | }
|
--------------------------+-------------------------
Dependiendo de las necesidades de diseño de la subrutina, se podrían utilizar los siguientes patrones de argumento de subrutina:
my ( $mandatory_parameters, $optional_parameters ) = @_;
Este patrón es útil si hay varios de cada uno. La belleza de este enfoque es que
$optional_parameters
no está definido si no se pasa, por lo que el caso predeterminado podría ejecutarseif ! $optional_parameters;
if ! $optional_parameters;
Tenga en cuenta que los parámetros obligatorios deberán verificarse posteriormente:
for ( qw/ a b c / ) { die "Missing ''$_'' parameter/n" unless exists $mandatory_parameters->{$_}; }
my ( $parameters ) = @_;
Útil si hay pocos o ningún parámetro obligatorio.
También es extremadamente efectivo si se pasan parámetros para modificar simplemente el comportamiento predeterminado. Al definir
$default_parameters
en el alcance del paquete, los valores predeterminados pueden ser cargados por una frase de línea subsiguiente a menos que un parámetro se haya pasado explícitamente:$parameters = { %$default_parameters, %$parameters };
Puede usar un punto y coma en el prototipo para indicar el final de los parámetros requeridos:
sub someFunction($$;$) {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
El ;
es opcional antes de un @
o %
, que, según los documentos , "engulle todo lo demás".
EDITAR: Como señala DVK en un comentario (y TLP enfatiza en otra respuesta aquí), probablemente esté mejor simplemente evitando los prototipos:
sub someFunction {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
Los prototipos de Perl tienen sus usos (principalmente para proporcionar coacción de contexto implícita a los argumentos, como hacen las funciones integradas de Perl). No deben usarse como un mecanismo para verificar que las funciones se llaman con el número y tipo de argumentos correctos.
Los prototipos (la parte ($$@)
de su declaración secundaria) son opcionales por sí mismos. Tienen un uso muy específico, y si no sabes qué es, es mejor no usarlo. Desde perlsub:
... la intención de esta función es principalmente permitirle definir subrutinas que funcionan como funciones integradas
Simplemente elimine el prototipo de su declaración secundaria y podrá usar los argumentos que desee.
sub someFunction {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
if (defined $option_param) {
# do optional things
}
$option_param //= "default optional value";
....
}