В одной из глав в Освоении Perl brian d foy показывает этот отрывок из Списка:: Util:
sub reduce(&@) {
my $code = shift;
no strict "refs";
return shift unless @_ > 1;
use vars qw($a $b);
my $caller = caller;
local(*{$caller . "::a"}) = \my $a;
local(*{$caller . "::b"}) = \my $b;
$a = shift;
foreach(@_) {
$b = $_;
$a = &{$code}();
}
$a;
}
Я не понимаю какой смысл use vars qw($a $b)
строка. Даже если я комментирую это, я получаю тот же вывод и предупреждения.
Это сделано потому, что List :: Util внутренне использует функцию reduce ().
В отсутствие use vars
при использовании функции выдается следующее предупреждение:
Name "List::MyUtil::a" used only once: possible typo at a.pl line 35.
Name "List::MyUtil::b" used only once: possible typo at a.pl line 35.
Вы можете убедиться в этом сами, запустив следующий код:
use strict;
use warnings;
package List::MyUtil;
sub reduce (&@) {
# INSERT THE TEXT FROM SUBROUTINE HERE - deleted to save space in the answer
}
sub x {
return reduce(sub {$a+$b}, 1,2,3);
}
package main;
my $res = List::MyUtil::x();
print "$res\n";
И затем снова запустив его. при использование переменных
отключено.
Как отмечает DVK, если мы запустим код с закомментированными use vars
, мы получим предупреждение о том, что переменные используются только один раз.
Другой способ подавить предупреждение - на стороне вызывающего абонента, то есть в вызове reduce
, а не в функции reduce
. Это необходимо делать при использовании функций из List :: Util
или List :: MoreUtils
, которые принимают ссылки на код (например, попарно
). Оба этих подхода работают на стороне вызывающего абонента:
my @sums = pairwise { no warnings 'once'; $a + $b } @x, @y;
my @sums = pairwise { our($a, $b); $a + $b } @x, @y;
Может быть, в это время параметр null
?
В абзаце сразу после этого кода объясняется. Существует сочетание пакетных и лексических переменных в одной области:
Остальная часть сокращения работает как сортировка, помещая два элемента в пакетные переменные $ a и $ b. Грэм определяет лексические переменные с этими именами и немедленно назначает typeglobs для $ a и $ b в вызывающем пакете с помощью символьных ссылок. После этого значения $ a и $ b являются лексическими версиями. Когда он вызывает аргумент подпрограммы & {$ code} (), этот код просматривает переменные пакета, которые действуют, когда я написал подпрограмму. Понял? Внутри уменьшите, я использую лексические версии, но внутри $ code, я использую версии пакета из вызывающего пакета. Вот почему Грэм сделал им псевдонимы друг друга.