Как передать необязательные параметры функции Perl?
Я хочу передать несколько параметров, один из которых является необязательным, для функции. Единственный способ сделать это, что я знаю, это использовать список (@) в качестве параметра. Таким образом, он не содержит ничего или 1 элемент (никогда не будет undef), поэтому я могу использовать следующий код:
sub someFunction([email protected]) {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
Этот код работает, но я чувствую, что, возможно, это не лучший обходной путь.
Есть ли другие способы сделать это?
Спасибо.
Ответы
Ответ 1
Вы можете использовать точку с запятой в прототипе, чтобы указать конец требуемых параметров:
sub someFunction($$;$) {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
;
является необязательным до @
или %
, который, согласно документам, "накапливает все остальное".
EDIT: Как отмечает DVK в комментарии (и TLP подчеркивает в другом ответе здесь), вы, вероятно, лучше всего избегаете прототипов:
sub someFunction {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
...
}
Прототипы Perl имеют свои возможности (в основном для обеспечения неявного контекстного принуждения к аргументам, как это делают встроенные функции Perl). Они должны не использоваться как механизм для проверки того, что функция вызывается с правильным числом и типом аргументов.
Ответ 2
Prototypes (часть ([email protected])
вашего дополнительного объявления) являются необязательными. Они имеют очень специфическое применение, и если вы не знаете, что это такое, лучше не использовать его. От perlsub:
... Цель этой функции - в первую очередь позволить вам определять подпрограммы которые работают как встроенные функции
Просто удалите прототип из вашего объявления sub, и вы можете использовать любые аргументы, которые вам нравятся.
sub someFunction {
my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
if (defined $option_param) {
# do optional things
}
$option_param //= "default optional value";
....
}
Ответ 3
Рекомендуется группировать параметры в $parameter
hashref. Это особенно полезно, если необходимо предоставить несколько параметров (обязательный или необязательный).
Чтобы получить доступ к любому параметру, просто используйте $parameter->{oblig1}
или $$parameter{option2}
.
Передача hashrefs делает его особенно удобным при разработке, поэтому, когда возникает потребность в $oblig3
, упорядочение аргументов изменяется ни на вызывающем, ни на самом sub. Сравните до и после:
# 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 ) = @_;
| }
--------------------------+-------------------------
Порядок аргументов изменяется как на вызывающем, так и на суб, поэтому порядок должен поддерживаться и соблюдаться.
Используя hashrefs, нет необходимости беспокоиться о порядке аргумента:
--------------------------+-------------------------
# Caller | # Sub
--------------------------+-------------------------
someFunc({ oblig1 => 1 | sub {
oblig2 => 2 | my ( $params ) = @_;
option1 => 1 | # No changes to
oblig3 => 7 | # argument passing
}); | }
|
--------------------------+-------------------------
В зависимости от требований к дизайну подпрограммы могут использоваться следующие шаблоны аргументов подпрограммы:
-
my ( $mandatory_parameters, $optional_parameters ) = @_;
Этот шаблон полезен, если его несколько. Красота этого подхода заключается в том, что $optional_parameters
undefined, если он не передан, поэтому может быть выполнен случай по умолчанию if ! $optional_parameters;
Обратите внимание, что обязательные параметры необходимо будет проверить впоследствии:
for ( qw/ a b c / ) {
die "Missing '$_' parameter\n"
unless exists $mandatory_parameters->{$_};
}
-
my ( $parameters ) = @_;
Полезно, если имеется несколько обязательных параметров или нет.
Это также чрезвычайно эффективно, если параметры передаются для простого изменения поведения по умолчанию. Определив $default_parameters
в объеме пакета, значения по умолчанию могут быть загружены с помощью следующего однострочного, если только параметр не был явно передан:
$parameters = { %$default_parameters, %$parameters };