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

时间:2011-11-14 15:48:51

标签: perl subroutine

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

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

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

3 个答案:

答案 0 :(得分:37)

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

  

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

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

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

答案 1 :(得分:18)

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

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

;@%之前是可选的,根据the docs,“吞噬其他所有内容”。

编辑:正如DVK在评论中指出的那样(而TLP在这里强调另一个答案),你可能最好只是避免原型:

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

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

答案 2 :(得分:14)

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

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

  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 };