Perl Hash引用相同哈希内的哈希值

时间:2017-07-19 07:30:30

标签: perl perl-hash

我的要求如下。在相同的散列内,键的值取决于其他键值,如下所示

my %test;

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

所以,当我这样做的时候     打印翻斗车(\%test); 我得到了

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

如果我更改哈希值

$test{map}{a} = 42

我得到了

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

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

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

如何达到上述效果?非常感谢任何帮助

2 个答案:

答案 0 :(得分:2)

您编写的代码的语义不是您想象的。特别是:

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

这些不是 - 我认为你想象 - 每次有人阅读时都会“规则”获取$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,也可以在线免费获得。

答案 1 :(得分:0)

您可以做的不是分配值,而是分配子程序。例如:

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";