Perl, (более легкий) доступ к хеш-переменным - PullRequest
1 голос
/ 30 января 2011

Я создал подфункцию, которая возвращает ссылку на хэш атрибутов, содержащий 7-8 переменных. Всякий раз, когда я хочу получить доступ к элементу, я либо переопределяю его my $n_players = $ref_attr->{'n_players'}, либо я называю его напрямую $ref_attr->{'n_players'}. Я бы предпочел использовать все переопределенные переменные (первый случай), однако это занимает 7-8 строк инициализации и загромождает мой код.

Есть ли модуль (который я не могу найти) или хороший метод экспорта ключей хеш-функции для использования в качестве переменных?

Ответы [ 5 ]

8 голосов
/ 30 января 2011

Вы можете использовать срезы хеша , чтобы уменьшить количество повторений при получении нескольких записей из хэша. Вы можете использовать это при инициализации ваших копий, например (при условии, что у вас также есть запись n_teams):

my ($n_players, $n_teams) = @$ref_attr{qw( n_players n_teams )};

Как предложил Эрик Стром, вы также можете использовать отступы, чтобы убедиться, что ключи расположены в правильном порядке:

my ($n_players, $n_teams) = @$ref_attr{
 qw( n_players   n_teams)
};

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

5 голосов
/ 30 января 2011

Вы можете легко сделать это с помощью ссылок и фрагментов хеша:

sub takes_hashref {
    my $hashref = shift;

    my ($one, $two, $three, $four, $five) = \@$hashref{
      qw(one   two   three   four   five)
    };

    print "one: $$one, two: $$two, three: $$three, ",
          "four: $$four, five: $$five\n";

    $_++ for $$one, $$three, $$five;
}

my %hash = qw(one 1 two 2 three 3 four 4 five 5);

takes_hashref \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7

@$hashref{qw(x y z)} - это фрагмент хеша, который возвращает список значений. Предварительное добавление \ принимает ссылку на каждое значение и возвращает список ссылок. Затем это присваивается вашим лексическим переменным. Когда вы используете каждую переменную, удвойте символ, чтобы разыменовать его: $$var. Поскольку эти переменные содержат ссылки на поля хеша, вы можете присвоить им: $$var = 'new val', и присвоение изменит исходный хеш. Если вас не волнуют изменения переменных, распространяющихся обратно в хеш, вы можете опустить \ в срезе хэша и двойной символ для всех переменных.

Если вы просто хотите создать более короткий псевдоним для работы, вы можете локализовать %_ в своей подпрограмме:

sub takes_hashref2 {
    my $hashref = shift;

    local *_ = \%$hashref;

    print "one: $_{one}, two: $_{two}, three: $_{three}, ",
          "four: $_{four}, five: $_{five}\n";

    $_++ for @_{qw(one three five)};
}

my %hash = qw(one 1 two 2 three 3 four 4 five 5);

takes_hashref2 \%hash; # one: 1, two: 2, three: 3, four: 4, five: 5
takes_hashref2 \%hash; # one: 2, two: 2, three: 4, four: 4, five: 6
takes_hashref2 \%hash; # one: 3, two: 2, three: 5, four: 4, five: 7

В строке local *_ = \%$hashref псевдонимы %_ к хешу в $hashref. Часть \% не обязательна, но выдает ошибку, если значение в $hashref не является хешем. Это просто более короткий способ написания:

die 'not a hash' unless ref $hashref eq 'HASH';
local *_ = $hashref;

И вы можете написать это в одной строке как:

local *_ = \%{shift @_};
3 голосов
/ 30 января 2011

Я второе предложение Хармена (не), но на случай, если вы сильно его хотите:

my %vars = ( a => 1, b => 2 );

while (my ($k,$v) = each %vars) {
    $::{$k} = \$v;
}

print "a=$a, b=$b\n";
3 голосов
/ 30 января 2011

Не.Либо скопируйте их явно (ваш первый вариант), либо просто используйте хэш (ваш второй вариант).Это намного яснее в долгосрочной перспективе.

...

, но если вы действительно этого хотите, хеш% :: - это текущий хэш переменной вашего пакета (да, внутренние компоненты perl).Вы можете играть с ним.

perl -e'print %::';
0 голосов
/ 31 января 2011

Другой вариант - создать класс для вашей коллекции данных и сделать так, чтобы подфункция возвращала экземпляр (объект) этого класса вместо простого хеширования.Затем вы получите доступ к значениям как $returned_object->n_players.В данном конкретном случае это не очень выгодно с точки зрения сохраненной типизации или более чистого внешнего вида по сравнению с $ref_attr->{n_players}, но переход к ООП открывает много возможностей (например, атрибуты только для чтения или вычисляемые атрибуты), которые могутне пригодится в будущем, поскольку ваша программа продолжает развиваться.

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