Я задаю этот вопрос, потому что я, наконец, решил проблему, в которой я пытался найти технику в ряде случаев. Я думаю, что это довольно аккуратно, поэтому я делаю Q-и-A на этом.Как вы локализуете ряд глобальных глобальных переменных без eval?
See, если я мог бы использовать eval
, я бы просто сделать это:
eval join("\n"
, map {
my $v = $valcashe{$_};
sprintf('$Text::Wrap::%s = %s', $_
, (looks_like_number($v) ? $v : "'$v'")
)
}
);
Text::Wrap::wrap('', '', $text);
Я даже пытался быть сложно, но, кажется, что local
локализует символ в блоке виртуальный, а не физический блок , Так что это не работает:
ATTR_NAME: while (@attr_names) {
no strict 'refs';
my $attr_name = shift;
my $attr_name = shift @attr_names;
my $attr_value = $wrapped_attributes{$attr_name};
my $symb_path = "Text\::Wrap\::$attr_name";
local ${$symb_path} = $attr_value;
next ATTR_NAME if @attr_names;
Text::Wrap::wrap('', '', $text);
}
же физический блок, и я проверил переменный пакет до и после того, как установить, и они даже показали правильное значение на их время цикла. Но тестирование показало, что только переменная last прошла через сохраненное значение для вызова wrap
. Поэтому значения только оставались локализованными до конца цикла.
Я думаю, что решение является опрятным - даже если тайная perl magick. Но конечный результат хорош, потому что это означает, что я могу обернуть устаревший код, который полагается на переменные с пакетной областью, и быть уверенным, что установленные значения будут максимально короткими.
Ужасно то, что в пакете есть глобалы, так как это интерфейс, это точно, и там многое происходит, что затрудняет понимание этого решения ... но, насколько решение идет, это довольно пятно, Я думаю. Тот факт, что вы даже можете сделать это в Perl, является свидетельством того, что все вокруг величие. Если бы это был модуль C, с которым вы работали, например, у вас не было бы никакого способа защитить эти глобальные шары от разгрома без каких-либо ИСТИННЫХ древних и волшебных магов! –