Как вы локализуете ряд унаследованных глобалов без eval? - PullRequest
4 голосов
/ 09 октября 2009

Я задаю этот вопрос, потому что наконец-то решил проблему, для которой пытался найти технику в ряде случаев. Я думаю, что это довольно аккуратно, поэтому я делаю вопросы и ответы по этому вопросу.

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

1 Ответ

6 голосов
/ 09 октября 2009

Аксеман, ты идиот! Хранилище пакета - тоже хеш ! Это работает:

local @Text::Wrap::{ keys %wrapped_attributes } 
    = \( values %wrapped_attributes )
    ;

Это делает следующее:

  1. Получает доступ к фрагменту массива таблицы символов Text::Wrap и возвращает именованные символы.
  2. Поскольку это символ , а не скаляр, для того, чтобы perl знал правильный слот, вы должны назначить ссылки . Это верно и для массивов и хэшей, но мы все знаем, что их ссылки более распространены.
  3. Синтаксис \( ... ) возвращает ссылку для каждого элемента в списке.

Таким образом, мы локализуем каждую переменную для каждой клавиши в %wrapped_attributes, и мы назначаем ей ссылку для каждого значения там.

Это уродливо и загадочно, и каждый раз, когда мне это нужно, трудно убрать его с дороги - но с его помощью я могу предварительно указать и задержать локализацию, чтобы выбрать места, где я могу установите предложенную Дэмиеном Конвеем колючую проволоку и знаки опасности.

Если я собираюсь использовать это, это должно быть просто ужасно, где я использую это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...