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

发布于 2024-12-16 02:12:11 字数 257 浏览 1 评论 0原文

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

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

    # ...
}

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

I want to pass several parameters, one of which is optional, to a function. The only way to do it that I know is using a list (@) as a parameter. Thus, it contents nothing or one element (will never be undef), so that I can use the following code:

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

    # ...
}

This code works, but I feel that maybe it's not the best workaround.
Are there any other ways to do it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浅黛梨妆こ 2024-12-23 02:12:11

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

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

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

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

Prototypes (the ($$@) part of your sub declaration) are optional themselves. They have a very specific use, and if you don't know what it is, it is better to not use it. From perlsub:

...the intent of this feature is primarily to let you define subroutines
that work like built-in functions

Just remove the prototype from your sub declaration, and you can use whatever arguments you like.

sub someFunction {
    my ( $oblig_param1, $oblig_param2, $option_param ) = @_;
    if (defined $option_param) {
        # do optional things
    }
    $option_param //= "default optional value";
    ....
} 
隐诗 2024-12-23 02:12:11

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

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

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

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

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

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

You can use a semicolon in the prototype to indicate the end of the required parameters:

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

The ; is optional before a @ or %, which, according to the docs, "gobbles up everything else".

As DVK points out in a comment (and TLP emphasizes in another answer here), you are probably best off simply avoiding prototypes:

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

Perl prototypes have their uses (mostly to supply implicit context coercion to arguments, as Perl's built-in functions do). They should not be used as a mechanism to check that function are called with the correct number and type of arguments.

我很坚强 2024-12-23 02:12:11

将参数分组到 $parameter hashref 中是一个好主意。如果需要提供多个选项(强制或可选),这尤其有用。

要访问任何参数,只需使用 $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 ) = @_;< /code>

如果每种模式都有多个,则此模式很有用。这种方法的美妙之处在于,如果不传递,$Optional_parameters 是未定义的,因此可以执行默认情况if ! $optional_parameters;

请注意,随后需要检查强制参数:

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

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

如果传递参数来简单地修改默认行为,这也是非常有效的。通过在包的范围内定义 $default_parameters ,除非显式传递参数,否则可以通过后续单行加载默认值:

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

It is a good idea to group parameters in a $parameter hashref. This is especially useful if several options (mandatory or optional) need to be provided.

To access any parameter, simply use $parameter->{oblig1} or $$parameter{option2}.

Passing hashrefs make it especially convenient when developing, so when the need for $oblig3 comes along, the ordering of the arguments changes neither at the caller nor the sub itself. Compare before and after:


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

The argument order changes at both caller and sub, so order needs to be maintained and respected.

Using hashrefs, there is no need to worry about argument order:

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

Depending on the design needs of the subroutine, the following subroutine argument patterns could be utilized:

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

This pattern is useful if there are several of each. The beauty of this approach is that $optional_parameters is undefined if not passed, so the default case could be executed if ! $optional_parameters;

Note that the mandatory parameters will need to be checked subsequently:

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

Useful if there are few or no mandatory parameters.

It is also extremely effective if parameters are passed to simply modify default behavior. By defining $default_parameters in the scope of the package, the defaults can be loaded by a subsequent one-liner unless a parameter was explicitly passed:

`$parameters = { %$default_parameters, %$parameters };`
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文