Шаблоны являются только инструментами и словарем. Вы пишете код, чтобы быть столь простыми, понятными и удобными в сопровождении, как Вы знаете как. Путем знания шаблонов у Вас есть больше альтернатив в Вашем распоряжении, и у Вас есть язык для обсуждения за и против подхода прежде, чем реализовать его.
В любом случае Вы только "переключаетесь" на "использование шаблона". Вы просто продолжаете делать то, что Вы всегда делаете, запишите код лучшим способом, Вы знаете как.
Скобки изменяют контекст, в котором grep
вычисляется, со скалярного контекста на контекст списка. В скалярном контексте grep
возвращает количество раз, когда выражение было истинным. В контексте списка он возвращает элементы, для которых выражение было истинным.
Следующее подчеркивает разницу, которую имеет контекст:
my $x = grep {/foo/} @array; # the number of things that match /foo/
my ($x) = grep {/foo/} @array; # the first thing that matches /foo/
my @foo = grep {/foo/} @array; # all the things that match /foo/
my (@foo) = grep {/foo/} @array; # all the things that match /foo/
Скобки предоставляют контекст списка для grep
. grep
затем фактически вернет список элементов, для которых выражение было истинным, а не только количество раз, когда выражение было истинным.
grep функция ведет себя по-разному в контексте списка и скалярном контексте. Это задокументировано в perldoc -f grep
:
Вычисляет BLOCK или EXPR для каждого элемента LIST (локально установка $ _ для каждого элемента) и возвращает значение списка состоящий из тех элементов, для которых вычислено выражение к истине. В скалярном контексте возвращает, сколько раз выражение было истинным.
Вы можете продублировать это самостоятельно с помощью плохо названной функции wantarray :
sub my_grep {
my $sub = shift;
my @return;
for my $item (@_) {
push @return if $sub->($item);
}
return @return if wantarray;
return scalar @return;
}
grep
возвращает список. Когда вы помещаете имя скалярной переменной в круглые скобки, Perl рассматривает все это l-значение как список, поэтому он присваивает этой переменной первое значение в списке.
Если бы у вас были другие скаляры в круглых скобках, вы бы получили второе, третье и т. д. значения из возвращаемого массива grep
в них:
my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array;
Я думаю, вы ищете first_index
из List :: MoreUtils :
use List::MoreUtils qw( first_index );
# ...
my $index = first_index { $_ eq $search_for } @array;
Кроме того, я думаю, что использование grep только для поиска первого экземпляра немного неэффективно, так как ему все равно нужно пройти и запустить обратный вызов для каждого элемента массива. Если ваш массив длинный, возможно, лучше написать цикл или использовать List :: MoreUtils, как указано выше.