我不知道如何为子例程设置默认参数。这是我考虑的:
sub hello {
print @_ || "Hello world";
}
如果您只需要一个论点,那效果很好。您将如何为多个参数设置默认值?
我打算这样做:
sub hello {
my $say = $_[0] || "Hello";
my $to = $_[1] || "World!";
print "$say $to";
}
但这是很多工作......必须有一个更简单的方法;可能是最佳实践?
我不知道如何为子例程设置默认参数。这是我考虑的:
sub hello {
print @_ || "Hello world";
}
如果您只需要一个论点,那效果很好。您将如何为多个参数设置默认值?
我打算这样做:
sub hello {
my $say = $_[0] || "Hello";
my $to = $_[1] || "World!";
print "$say $to";
}
但这是很多工作......必须有一个更简单的方法;可能是最佳实践?
我用这样的命名参数来做:
sub hello {
my (%arg) = (
'foo' => 'default_foo',
'bar' => 'default_bar',
@_
);
}
我相信Params::Validate支持默认值,但这比我喜欢的要麻烦。
我通常会做类似的事情:
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"
)。
也看看Method::Signatures
。这用于Devel::Declare
通过关键字method
和func
.
以下是您使用 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/
如果您看到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 最佳实践。
因为 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
。
我最喜欢这种方式:从 Perl 5.10 开始,您可以使用它//
来检查变量是否已定义,并在未定义时提供替代值。所以,一个简单的例子是:
我的 $DEFAULT_VALUE = 42;
sub f {
my ($p1, $p2) = @_;
$p1 //= 'DEFAULT';
$p2 // = $DEFAULT_VALUE;
}
另一种选择是使用shift
指令从以下位置获取参数@_
:
sub f {
my $p1 = shift // 'DEFAULT';
}
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');
解决您的问题的最佳方法已在其他答案中讨论。
不过让我印象深刻的一件事是你说:
sub hello { print @_ || "Hello world"; }
如果您只需要一个论点,这很好用。
你真的试过那个代码吗?它将打印参数的数量,或者,当没有提供时,Hello World
!
这样做的原因是 || 运算符优先并在标量上下文中强制左侧,从而减少@_
您提供的参数数量,而不是参数本身!
查看perlop以获取有关 Perl 中运算符的更多信息。
HTH,
保罗
有关更多糖,另请参阅Method::Signatures:
func add($this = 23, $that = 42) {
return $this + $that;
}