我不知道如何为子程序设置默认参数。这是我考虑的:
sub hello {
print @_ || "Hello world";
}
如果您需要的只是一个参数,那就可行。您将如何为多个参数设置默认值?
我打算这样做:
sub hello {
my $say = $_[0] || "Hello";
my $to = $_[1] || "World!";
print "$say $to";
}
但那是很多工作......必须有一个更简单的方法;可能是最好的做法?
答案 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
为关键字method
和func
提供额外的(必需!)糖。
以下是使用新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>
示例:强>
#!/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';
}