这是一个非常基本的Perl问题,但我只是想确保实际的良好做法。
考虑我已经构建了一个函数来修剪字符串中的空格,我会将单个标量作为字符串或字符串数组传递给它,我有这个基本的工作示例:
sub trim_spaces {
my (@out) = @_;
for (@out) {
s/\s+//g;
}
return (scalar @out >1)? @out : $out[0];
}
这适用于以下调用:
trim_spaces(" These Spaces Are All Removed");
和
@str = (" Str Number 1 ", " Str Number 2 ", " Str Number 3 ");
trim_spaces(@str);
我想要做的和理解的是这个函数的最短版本,如下所示:
sub trim_spaces {
s/\s+//g for (@_);
return @_;
}
仅当我传递数组时才有效:
trim_spaces(@str);
但是如果我传递标量字符串则不起作用:
trim_spaces(" These Spaces Are All Removed");
我知道它应该从标量引用转换为数组,如何在短版本中完成。
尝试了解Perl的最佳实践。
答案 0 :(得分:5)
严格的最佳实践答案是始终将@_
的内容解压缩为词法变量。 Perl最佳实践提供以下(释义)参数:
直接访问@_
不是自我记录。 $_[0]
,$_[1]
等等,不会告诉您这些参数的用途。
@_
的别名行为很容易被遗忘,并且可能成为程序中难以发现的错误的来源。只要有可能,避免在远处做出怪异的行为。
您可以在解压缩@_
数组时验证每个参数。
一个论点不是来自PBP:
my $self = shift;
清楚地将其标记为OO方法,而不是普通的子。资料来源:Perl最佳实践(Conway 2005),Perl::Critic来自PBP的相关政策。
@_中的元素是原始值的别名,这意味着在子例程中修改它们也会将它们更改为外部值。您返回的数组将在示例中被忽略。
如果将字符串存储在变量中,这将起作用:
my $string = ' These Spaces Are Removed ';
trim_spaces($string); # $string is now 'TheseSpacesAreRemoved'
或者您可以使用非破坏性替换并分配由此创建的结果:
sub trim_spaces { return map { s/\s+//gr } @_ }
my @trimmed = trim_spaces('string one', ' string two');
my ($trimmed_scalar) = trim_spaces('string three');
map
将创建一个由<{1}}标志替换的 r 值列表。 $ trimmed_scalar周围的parens是必要的;请参阅最后一个不是版本的示例。
或者,您可以将子例程中的参数复制到词法变量中以避免在远处执行操作,这通常比直接修改@_的元素更好:
/r
就个人而言,当子程序返回没有副作用的值时,我发现它更好,而sub trim_spaces
{
my @strings = @_;
s/\s+//g for @strings;
return @strings;
}
标志使我省去了为词法副本考虑更好名称的麻烦。我们可以使用/r
使其在调用上下文方面更加智能:
wantarray
在旁注中,sub trim_spaces
{
return if not defined wantarray;
return map { s/\s+//gr } @_ if wantarray;
return shift =~ s/\s+//gr;
}
会更好地命名为trim_spaces
或类似名称。修剪通常意味着删除前导和尾随空格,remove_whitespace
字符类除了空格外还匹配制表符,换行符,换页符和回车符。如果这是您想要的,请使用\s
删除空格。