Написание рефлексивного метода для загрузки переменных из файла conf и назначения ссылок?
Я работаю с уродливым кодом и пытаюсь выполнить очистку путем перемещения значений в модуле в файл конфигурации. Я хочу сохранить значения модулей по умолчанию, если переменная не существует в файле conf, в противном случае используйте версию файла conf. В модуле много (слишком много) переменных, поэтому я хотел, чтобы вспомогательный метод поддерживал это. Это первый шаг рефакторинга, я, вероятно, пойду дальше, чтобы лучше обрабатывать переменные конфигурации позже, но по одному шагу за раз.
Я хочу метод, который будет принимать переменную в моем модуле и либо загружать значение из conf или установить значение по умолчанию. Так что-то вроде этого (пишу это с нуля, поэтому пока воспринимайте это как псевдокод)
Our ($var_a, $var_b ...);
export($var_a, $var_b ...);
my %conf = #load config file
load_var(\$var_a, "foo");
load_var(\$var_b, "$var_abar");
sub load_var($$){
my($variable_ref, $default) = @_
my $variale_name = Dumper($$variable_ref); #get name of variable
my $variable_value = $conf{$variable_name} // $default;
#update original variable by having $variable_ref point to $variable_value
}
Итак, два вопроса здесь. Во-первых, кто-нибудь знает, существует ли какая-либо функциональность, такая как мой load_var, которую я повторно использую?
Во-вторых, если я должен написать это с нуля, могу ли я сделать это с версией perl старше 5.22? когда я читаю perlref, он ссылается на установку ссылок как на новую функцию в 5.22, но кажется странным, что такое базовое поведение ссылок не было реализовано раньше, поэтому мне интересно, неправильно ли я понял документ. Есть ли способ передать переменную в мой метод load_var и убедиться, что она действительно обновлена?
1 ответ
Для такого рода проблем я бы подумал об использовании AUTOLOAD - я знаю, что это не совсем то, о чем вы просили, но это похоже на нечто подобное:
Если вы вызываете подпрограмму, которая не определена, вы обычно получаете немедленную фатальную ошибку с жалобой на то, что подпрограмма не существует. (Аналогично для подпрограмм, используемых в качестве методов, когда метод не существует ни в одном базовом классе пакета класса.) Однако, если подпрограмма AUTOLOAD определена в пакете или пакетах, используемых для поиска исходной подпрограммы, тогда эта подпрограмма AUTOLOAD вызывается с аргументами, которые были бы переданы исходной подпрограмме.
Что-то вроде:
#!/usr/bin/env perl
package Narf;
use Data::Dumper;
use strict;
use warnings;
our $AUTOLOAD;
my %conf = ( fish => 1,
carrot => "banana" );
sub AUTOLOAD {
print "Loading $AUTOLOAD\n";
##read config file
my $target = $AUTOLOAD =~ s/.*:://gr;
print $target;
return $conf{$target} // 0;
}
sub boo {
print "Boo!\n";
}
Вы можете назвать это OO-стилем или просто "нормально", но имейте в виду, что это создает подпрограммы, а не переменные, поэтому вам может потребоваться указать пакет (или иначе "форсировать" импорт / экспорт)
#!/usr/bin/env perl
use strict;
use warnings;
use Narf;
print Narf::fish(),"\n";
print Narf::carrot(),"\n";
print Narf::somethingelse(),"\n";
print Narf::boo;
Примечание. Поскольку они загружаются автоматически, они не находятся в локальном пространстве имен. Относительно переменных у вас есть это обсуждение perlmonks, но я не уверен, что это хорошая линия для принятия, по всем причинам, изложенным в разделе Почему глупо "использовать переменную как имя переменной"