Все, что вам нужно сделать, это заменить @_
на @_ ? @_ : $_
в аргументе для цикла for
.
sub trim {
for (@_ ? @_ : $_) {
s|^\s+||;
s|\s+$||;
}
}
Согласно ответу ikegami, возникает неприятная проблема:делать с лексикой $_
(объявленной с my $_;
), поскольку эта версия $_
не глобальна, а привязана к лексической панели.
Прототип (_)
является одним из способовчтобы решить эту проблему, но это также означает, что подпрограмма принимает только один аргумент, и этот аргумент имеет скалярный контекст, что делает его таким же плохим, как и прототип ($)
(из-за непреднамеренных последствий скалярного контекста).
Каждый раз, когда вы пытаетесь сотворить магию на лексике, вам пригодится модуль 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]"
Лично я просто избегаю лексических $_
и такие ужасные проблемы просто исчезают.Но если вам нужно это поддержать, это способ.