Я задаю этот вопрос, потому что наконец-то решил проблему, для которой пытался найти технику в ряде случаев. Я думаю, что это довольно аккуратно, поэтому я делаю вопросы и ответы по этому вопросу.
Смотрите, если бы я мог использовать 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. Но конечный результат хорош, потому что это означает, что я могу обернуть унаследованный код, который опирается на переменные области пакета, и быть уверенным, что набор значений будет максимально коротким.