【问题标题】:Binding two Perl hashes (not two anonymous hashes)绑定两个 Perl 哈希(不是两个匿名哈希)
【发布时间】:2015-09-11 20:21:18
【问题描述】:

为了重用一些已经编写好的代码库,我需要将一个散列(%bar)“伪装”成另一个散列(%foo),这样%bar 中所做的每个更改都可以通过%foo 看到他们的绑定之后。​​

使用匿名哈希结构很简单:只需将bar 的引用复制到foo 的引用中($foo = $bar;)。

“不使用”匿名散列怎么样(因为我必须重用的代码不是使用匿名散列结构构建的)?只有这样吗?

谢谢。

use strict;
use Data::Dumper;

my  %foo = ();
my  %bar = ();

%foo = %bar;    # This won't work as it copies %bar into %foo as at the current time.

$bar{A}->{st} = 'a';
$bar{A}->{qt} = 'a';
$bar{B}->{st} = 'b';
$bar{B}->{qt} = 'b';

# $foo{A}->{st}  doesn't exist

当然,匿名哈希构造会是一件好事。

use strict;
use Data::Dumper;

my  $foo = {};
my  $bar = {};

$foo = $bar;   # This works fine.

$bar->{A}->{st} = 'a';
$bar->{A}->{qt} = 'a';
$bar->{B}->{st} = 'b';
$bar->{B}->{qt} = 'b';

print STDOUT "foo\n---\n";
print Dumper($foo) . "\n\n";

print STDOUT "bar\n---\n";
print Dumper($bar) . "\n\n";

产生预期的结果:

foo
---
$VAR1 = {
          'B' => {
                   'st' => 'b',
                   'qt' => 'b'
                 },
          'A' => {
                   'qt' => 'a',
                   'st' => 'a'
                 }
        };


bar
---
$VAR1 = {
          'B' => {
                   'st' => 'b',
                   'qt' => 'b'
                 },
          'A' => {
                   'qt' => 'a',
                   'st' => 'a'
                 }
        };

【问题讨论】:

  • 您为什么要这样做?听起来你让你的生活变得艰难。总体意图是什么?
  • 正如我所写,我必须重用一个我不允许修改的现有库,将新内容(我的内容)映射到现有的哈希(不是我的),然后由它处理图书馆。如果只是为了我,我不会打扰。因此,我想了解该语言是否允许 %foo=(); 被另一个现有构造函数替换。谢谢。
  • 你能改写一下吗?有创建哈希变量的代码。那是词汇还是全局?它在一个包裹里吗?是函数调用的返回值吗?
  • 不,一堆(相当)独立的文件与“require()”放在一起。我正在修改其中一个将创建%bar 内容。我可以协商添加一行来创建“bar linked to foo”。如果允许我修改现有代码,我会立即将其全部转为非散列。一般来说 - 不是在谈论我的(可怜的)案例 - 是否可以将 %bar=(); 创建的构造函数替换为另一个?
  • %bar = () 中没有构造函数。 %bar 只是一个哈希,而不是一个对象。您正在使用空列表初始化它(如果它之前没有值)。使用my %bar,您正在声明它。如果有一个构造函数,您可以通过子类化或猴子修补到您的包中来覆盖它。但是您似乎没有包裹,所以这是不可能的。为了避免进一步的混乱,你可以做的是在包中编写新代码,并开始慢慢摆脱遗留的东西。当您需要使用它时,也将它放在一个包中。 package legacy { require 'foo.pl' }

标签: perl hash


【解决方案1】:

对于您的示例,您可以使用 Data::Alias%bar 别名为 %foo。这使您可以在 %bar 中进行更改,然后在 %foo 中查看。

use strict;
use warnings;
use Data::Printer;
use Data::Alias;

my  %foo = ();
my  %bar = ();

alias %foo = %bar;

$bar{A}->{st} = 'a';
$bar{A}->{qt} = 'a';
$bar{B}->{st} = 'b';
$bar{B}->{qt} = 'b';

p %foo;
p %bar;

输出:

{
    A   {
        qt   "a",
        st   "a"
    },
    B   {
        qt   "b",
        st   "b"
    }
}
{
    A   {
        qt   "a",
        st   "a"
    },
    B   {
        qt   "b",
        st   "b"
    }
}

【讨论】:

  • 谢谢。因此,这意味着该语言不允许这样做,因此需要使用外部代码。我是否在某处读到 Data:Alias 正在操纵 Perl 内部数据结构来实现这一壮举?因此导致一些向上兼容性问题的不确定性。这不适合客户。我想我必须申请重写我提到的这些外部文件(并触发一些复杂的重新验证过程)。我们的生活就这样结束了。还是非常感谢。
  • 我相信确实如此。查看源代码会发现 2k 行漂亮的 XS 代码。但是你不能真正知道它是否在上游做了任何事情。您可以进行测试,但我想您没有该项目的测试。另一方面,不应搁置使用 CPAN。这是一项宝贵的资产,也是当今 Perl 相对于新技术的优势之一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-18
  • 2016-09-05
  • 1970-01-01
  • 2012-12-19
  • 2011-09-12
  • 1970-01-01
相关资源
最近更新 更多