14

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

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

如果您只需要一个论点,那效果很好。您将如何为多个参数设置默认值?

我打算这样做:

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

但这是很多工作......必须有一个更简单的方法;可能是最佳实践?

4

9 回答 9

14

我用这样的命名参数来做:

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

}

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

于 2010-08-22T22:11:26.983 回答
13

我通常会做类似的事情:

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

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

于 2010-08-22T22:01:20.823 回答
7

也看看Method::Signatures。这用于Devel::Declare通过关键字methodfunc.

以下是您使用 new 的示例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/

于 2010-08-23T08:40:03.350 回答
4

如果您看到Damian Conway的Perl Best Practices : Default argument Values的文档,那么您会发现一些要点,例如:

  • 解压缩 @_ 后立即解析任何默认参数值。
  • 它建议如果您要设置许多默认值,那么最干净的方法是将默认值分解到表中,即散列 ,然后使用该表预初始化参数散列。

例子:

#!/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 最佳实践

于 2010-08-23T08:35:39.980 回答
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 中添加的。它比使用逻辑或 ( ||) 更健壮,因为它不会默认逻辑上的错误值''0

于 2010-08-22T22:04:47.000 回答
4

我最喜欢这种方式:从 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

于 2018-10-15T14:47:47.320 回答
2

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

我也看到人们使用my $var = exists @_[0] ? shift : "Default_Value";,但是 Perl 的文档指出调用exists数组已被弃用,所以我不会真正推荐它。

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');
于 2010-08-22T22:00:53.477 回答
1

解决您的问题的最佳方法已在其他答案中讨论。
不过让我印象深刻的一件事是你说:

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

如果您只需要一个论点,这很好用。

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

HTH,
保罗

于 2010-08-23T12:07:19.013 回答
0

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

func add($this = 23, $that = 42) {
    return $this + $that;
}
于 2010-08-23T15:48:16.053 回答