子例程中的默认参数值

时间:2010-08-22 21:49:51

标签: perl function subroutine

我不知道如何为子程序设置默认参数。这是我考虑的:

sub hello {
  print @_ || "Hello world";
}

如果您需要的只是一个参数,那就可行。您将如何为多个参数设置默认值?

我打算这样做:

sub hello {
  my $say = $_[0] || "Hello";
  my $to  = $_[1] || "World!";
  print "$say $to";
}

但那是很多工作......必须有一个更简单的方法;可能是最好的做法?

9 个答案:

答案 0 :(得分:14)

我使用像这样的命名参数:

sub hello {
    my (%arg) = (
        'foo' => 'default_foo',
        'bar' => 'default_bar',
        @_
    );

}

我相信Params::Validate支持默认值,但这比我想要的更麻烦。

答案 1 :(得分:11)

我通常会这样做:

sub hello {
    my ($say,$to) = @_;
    $say ||= "Hello";
    $to ||= "World!";
    print "$say $to\n";
}

请注意,从perl 5.10开始,您可以使用“//=”运算符来测试变量是否已定义,而不仅仅是非零。 (想象一下使用上面的调用hello("0","friend")会产生"Hello friend",这可能不是你想要的。使用//=运算符会产生"0 friend"

答案 2 :(得分:5)

另请查看Method::Signatures。这会使用Devel::Declare为关键字methodfunc提供额外的(必需!)糖。

以下是使用新func

的示例
use Method::Signatures;

func hello ($say='Hello', $to='World!') {
    say "$say $to";
}

hello( 'Hello', 'you!' );    # => "Hello you!"
hello( 'Yo' );               # => "Yo World!"
hello();                     # => "Hello World!"

/ I3az /

答案 3 :(得分:4)

因为Perl将参数传递给子例程的机制是单个列表,所以参数是位置的。这使得很难提供默认值。一些内置函数(例如substr)通过根据使用它们的可能性来排序参数来处理这一点 - 不常使用的参数出现在最后并具有有用的默认值。

更简洁的方法是使用命名参数。 Perl不支持命名参数本身,但您可以使用哈希模拟它们:

use 5.010;  # for //

sub hello {
    my %arg = @_;
    my $say = delete $arg{say} // 'Hello';
    my $to  = delete $arg{to}  // 'World!';
    print "$say $to\n";
}

hello(say => 'Hi', to => 'everyone');  # Hi everyone
hello(say => 'Hi');                    # Hi world!
hello(to  => 'neighbor Bob');          # Hello neighbor Bob
hello();                               # Hello world!

注意:在Perl v5.10中添加了defined-或operator //。它比使用逻辑或(||)更健壮,因为它不会默认为逻辑错误值''0

答案 4 :(得分:2)

CPAN上有Attribute::Default个模块。可能比这更干净,并避免了一些复杂性(例如,如果你想将false传递给你的子程序怎么办?)。

我也看到人们使用my $var = exists @_[0] ? shift : "Default_Value";,但Perl的文档指出calling exists on arrays is deprecated,所以我不会真的推荐它。

文档页面中Attribute::Default的摘录:

  sub vitals : Default({age => 14, sex => 'male'}) {
     my %vitals = @_;
     print "I'm $vitals{'sex'}, $vitals{'age'} years old, and am from $vitals{'location'}\n";
  }

   # Prints "I'm male, 14 years old, and am from Schenectady"
   vitals(location => 'Schenectady');

答案 5 :(得分:2)

如果您通过 Damian Conway 看到 Perl最佳实践默认参数值的文档,那么您会发现一些重要的观点,例如:< / p>

  • 解包@_后立即解析所有默认参数值
  • 它建议如果您要设置许多默认值,那么最干净的方法是将默认值分解为表,即。,哈希,然后使用该表预先初始化参数哈希。 / LI>

示例:

#!/usr/bin/perl
  use strict;
  use warning;
  my %myhash = (say => "Hello", to => "Stack Overflow");
  sub hello {
   my ($say, $to) = @_;
   $say =  $say ? $say : $myhash{say};
   $to =  $to ? $to : $myhash{to};
   print "$say $to\n";
  }
  hello('Perl');      # output :Perl Stack Overflow
  hello('','SO');     # output :Hello SO
  hello('Perl','SO'); # output :Perl SO
  hello();            # output :Hello Stack Overflow

有关详细信息和完整示例,请参阅 Perl Best Practices

答案 6 :(得分:1)

其他答案中讨论了解决问题的最佳方法 但令我印象深刻的是你说:

sub hello {
   print @_ || "Hello world";
}
     

如果您需要的只是一个参数,这样就可以了。

你真的试过那段代码吗?它将打印参数的数量,或者,如果没有提供,则打印Hello World
这样做的原因是|| -operator优先并在标量上下文中强制左侧,从而将@_减少为您提供的参数数量,而不是参数本身!
有关Perl中运算符的更多信息,请查看perlop

HTH,
保罗

答案 7 :(得分:0)

有关更多糖的信息,另请参阅Method::Signatures

func add($this = 23, $that = 42) {
    return $this + $that;
}

答案 8 :(得分:0)

我最喜欢这种方式:从Perl 5.10开始,您可以使用//检查是否定义了变量,并在变量未定义的情况下提供替代值。 因此,一个简单的例子是:

我的$ DEFAULT_VALUE = 42;

sub f {
    my ($p1, $p2) = @_;
    $p1 //= 'DEFAULT';
    $p2 // = $DEFAULT_VALUE;
}

另一种选择是使用shift指令从@_获取参数:

sub f {
    my $p1 = shift // 'DEFAULT';
}

来源:https://perlmaven.com/how-to-set-default-values-in-perl