Perl Hash 引用同一哈希中的哈希值

Perl Hash references to the hash values inside same hash

我的要求如下。在同一个散列中,键的值依赖于其他键值,如下所示

my %test;

$test{map}{a} = 32;
$test{map}{b} = $test{map}{a}+10;
$test{ref}{r} = $test{map}{b};

所以,当我这样做的时候 打印转储程序(\%测试); 我得到

$VAR1 = {
          'ref' => {
                     'r' => 42
                   },
          'map' => {
                     'a' => 32,
                     'b' => 42
                   }
        };

如果我更改哈希值

$test{map}{a} = 42

我明白了

$VAR1 = {
          'ref' => {
                     'r' => 42
                   },
          'map' => {
                     'a' => 42,
                     'b' => 42
                   }
        };

相反,我应该有更新后的哈希 %test,如下所示

$VAR1 = {
          'ref' => {
                     'r' => 52
                   },
          'map' => {
                     'a' => 42,
                     'b' => 52
                   }
        };

如何实现上面的结果?非常感谢任何帮助

你写的代码语义不是你想象的那样。特别是:

$test{map}{b} = $test{map}{a}+10;
$test{ref}{r} = $test{map}{b};

这些不是-我想你想象的-"rules"每次有人阅读时都获得$test{map}{b}$test{map}{b}的值它们,而是在执行时修改与键 br 关联的值的指令。就是这样。

如果您希望散列中的元素是动态的,一种可能的方法是使用对子例程的引用,以及一种在用户请求值时评估这些规则的机制。但请注意,这可能会变得复杂:例如,循环引用呢?或者引用其他规则的规则,如示例中的键 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 的角度对这些技术感兴趣,一本非常好的书是 Higher Order 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";