Perl Hash ссылается на значения хеша внутри того же хеша
Мое требование, как показано ниже. Внутри того же хеша значения ключей зависят от другого значения ключа, как показано ниже
my %test;
$test{map}{a} = 32;
$test{map}{b} = $test{map}{a}+10;
$test{ref}{r} = $test{map}{b};
Итак, когда я делаю печать Dumper(\%test); я получил
$VAR1 = {
'ref' => {
'r' => 42
},
'map' => {
'a' => 32,
'b' => 42
}
};
Если я изменю значение хеша
$test{map}{a} = 42
я получил
$VAR1 = {
'ref' => {
'r' => 42
},
'map' => {
'a' => 42,
'b' => 42
}
};
Вместо этого у меня должен быть обновленный тест hash %, как показано ниже
$VAR1 = {
'ref' => {
'r' => 52
},
'map' => {
'a' => 42,
'b' => 52
}
};
Как добиться вышеуказанного результата? Любая помощь высоко ценится
2 ответа
Семантика написанного вами кода не та, которую вы себе представляли. Особенно:
$test{map}{b} = $test{map}{a}+10;
$test{ref}{r} = $test{map}{b};
Это не - как я думаю, вы себе представляли - "правила" для получения значения $test{map}{b}
а также $test{map}{b}
каждый раз, когда кто-то их читает, но инструкции, которые при выполнении изменяют значение, связанное с ключами b
а также r
, И это все.
Если вы хотите, чтобы элементы в вашем хэше были динамическими, одним из возможных подходов может быть использование ссылок на подпрограммы, а также механизм для оценки этих правил, когда пользователь запрашивает значения. Но имейте в виду, что это может быть сложно: например, как насчет циклических ссылок? Или правила, которые ссылаются на другие правила, в качестве ключа r
в твоем примере?
В любом случае, вот код для доказательства концепции:
use strict;
use warnings;
use v5.10;
my %test;
$test{map}{a} = 32;
$test{map}{b} = sub { evaluate( $test{map}{a} ) + 10 };
$test{ref}{r} = sub { evaluate( $test{map}{b} ) };
sub evaluate {
my $expr = shift;
if ( ref $expr eq 'CODE' ) {
# We need to execute the procedure indicated
# to obtain a value
return $expr->();
}
else {
# Otherwise, we just return what we found associated to the key
return $expr;
}
}
say evaluate( $test{ map }{ a } ); # 32
say evaluate( $test{ map }{ b } ); # 42
say evaluate( $test{ ref }{ r } ); # 42
$test{map}{a} = 42;
say evaluate( $test{ map }{ a } ); # 42
say evaluate( $test{ map }{ b } ); # 52
say evaluate( $test{ ref }{ r } ); # 52
Опять же, разработка общего и твердого решения ни в коем случае не является тривиальным проектом. Если вы интересуетесь этими методами с точки зрения Perl, очень хорошая книга - Perl высшего порядка, также доступная онлайн бесплатно.
Что вы можете сделать, это вместо присвоения значения назначить подпрограмму. Например:
my %test;
$test{map}{a} = 32;
$test{map}{b} = sub { return $test{map}{a}+10; };
$test{ref}{r} = sub { return $test{map}{b}(); };
print $test{ref}{r}() . "\n";
$test{map}{a} = 42;
print $test{ref}{r}() . "\n";