1

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

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

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

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

如何达到上述结果?任何帮助深表感谢

4

2 回答 2

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,也可以免费在线获得。

于 2017-07-19T09:04:09.310 回答
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";
于 2017-07-19T09:07:57.233 回答