2009-10-08 1 views
4

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

ответ

6

Axeman, вы идиот! Пакет сета - хэш тоже! Это работает:

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

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

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

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

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

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

+0

Ужасно то, что в пакете есть глобалы, так как это интерфейс, это точно, и там многое происходит, что затрудняет понимание этого решения ... но, насколько решение идет, это довольно пятно, Я думаю. Тот факт, что вы даже можете сделать это в Perl, является свидетельством того, что все вокруг величие. Если бы это был модуль C, с которым вы работали, например, у вас не было бы никакого способа защитить эти глобальные шары от разгрома без каких-либо ИСТИННЫХ древних и волшебных магов! –