如何将可选参数传递给 Perl 函数?

问题描述 投票:0回答:3

我想将多个参数传递给函数,其中一个参数是可选的。据我所知,唯一的方法是使用列表(@)作为参数。因此,它不包含任何内容或一个元素(永远不会是 undef),以便我可以使用以下代码:

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

    # ...
}

这段代码有效,但我觉得这可能不是最好的解决方法。 还有其他办法吗?

perl subroutine
3个回答
42
投票

原型(子声明的

($$@)
部分)本身是可选的。它们有非常具体的用途,如果您不知道它是什么,最好不要使用它。来自 perlsub:

...此功能的目的主要是让您定义子例程 就像内置函数一样工作

只需从子声明中删除原型,您就可以使用您喜欢的任何参数。

sub someFunction {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    if (defined $option_param) {
        # do optional things
    }
    $option_param //= "default optional value";
    ....
} 

21
投票

可以在原型中使用分号来表示所需参数的结束:

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

;
@
%
之前是可选的,根据文档,“吞噬其他一切”。

正如 DVK 在评论中指出的那样(TLP 在此处的另一个答案中强调),您可能最好只是避免原型:

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

Perl 原型有其用途(主要是为参数提供隐式上下文强制,就像 Perl 的内置函数一样)。它们不应该被用作检查函数是否使用正确数量和类型的参数进行调用的机制。


16
投票
$parameter

哈希引用中是个好主意。如果需要提供多个选项(强制或可选),这尤其有用。


要访问任何参数,只需使用

$parameter->{oblig1}

$$parameter{option2}

传递 hashref 使其在开发时特别方便,因此当需要

$oblig3

时,参数的顺序既不会在调用者处发生变化,也不会在子进程本身发生变化。前后对比:


# 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 }); | } | --------------------------+-------------------------


根据子程序的设计需要,可以使用以下子程序参数模式:

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

    
    
    如果每种模式都有多个,则此模式很有用。这种方法的优点在于,如果不通过,

    $optional_parameters

    是未定义的,因此可以执行默认情况

    if  ! $optional_parameters;
    
    
    请注意,随后需要检查强制参数:

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

  2. my ( $parameters ) = @_;

    
    
    如果强制参数很少或没有,很有用。

    如果传递参数来简单地修改默认行为也是非常有效的。通过在包的范围内定义

    $default_parameters

    ,除非显式传递参数,否则可以通过后续单行加载默认值:

    
    

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

    
    

© www.soinside.com 2019 - 2024. All rights reserved.