我有trim
例程:
sub trim {
for (@_) {
s|^\s+||;
s|\s+$||;
}
}
它修剪空白"就地",即:
trim $x, $y;
将修剪$ x和$ y的空白(修改它们)。
如何改进trim
,以便我可以将其称为:
trim;
,这将与:
相同trim $_;
答案 0 :(得分:11)
只需检查是否没有提供参数:
use strict;
use warnings;
$_=" abc ";
sub trim
{
if(@_)
{
foreach my $i(@_)
{
$i=~s/^\s+//;
$i=~s/\s+$//;
}
}
else
{
s/^\s+//;
s/\s+$//;
}
}
trim;
print "!$_!\n"; #Throwing in exclamation points just to make sure white space is gone.
这会产生输出
!abc!
答案 1 :(得分:11)
您需要做的就是在@_
循环的参数中将@_ ? @_ : $_
替换为for
。
sub trim {
for (@_ ? @_ : $_) {
s|^\s+||;
s|\s+$||;
}
}
根据ikegami的回答,关于如何处理词汇$_
(用my $_;
声明)的问题有一个唠叨的问题,因为$_
版本不是全局的,但是绑在一个词汇垫上。
(_)
原型是解决这个问题的一种方法,但它也意味着子程序只接受一个参数,并且参数具有标量上下文,这使得它与{{1}一样糟糕原型(由于标量上下文的意外后果)。
每当试图在词汇上做魔术时,模块PadWalker就派上用场了。所以这是一个在列表上正常工作的版本,适用于词法和全局($)
,并且它不会在调用站点上强制使用标量上下文:
$_
就个人而言,我只是避免使用词汇use PadWalker 'peek_my';
sub trim {
my $it;
unless (@_) {
my $pad = peek_my 1;
$it = $$pad{'$_'} || \$::_
}
for (@_ ? @_ : $$it) {
s/^\s+//;
s/\s+$//;
}
}
{local $_ = " a "; trim; say "[$_]"} # prints "[a]"
{my $_ = " a "; trim; say "[$_]"} # prints "[a]"
{my $x = " a "; trim $x; say "[$x]"} # prints "[a]"
,这样的丑陋问题就会消失。但如果你需要支持它,这是一种方式。
答案 2 :(得分:4)
如果您的trim
只拿了一个arg,则可以使用_
原型。
sub trim(_) {
for ($_[0]) {
s|^\s+||;
s|\s+$||;
}
}
然后所有这些都可行:
{ local $_ = " abc "; trim; say; }
{ my $_ = " abc "; trim; say; }
{ my $x = " abc "; trim $x; say $x; }
但由于您的trim
会获取args列表,因此您无法使用_
原型。您必须使用@_ ? @_ : $_
。
sub trim {
for (@_ ? @_ : $_) {
s|^\s+||;
s|\s+$||;
}
}
但这意味着它不适用于词汇$_
。
{ local $_ = " abc "; trim; say; }
{ my $_ = " abc "; trim; say; } # XXX $::_ changed instead of $_
{ my $x = " abc "; trim $x; say $x; }