1

这是要处理的绑定哈希的预期和直观行为$h{a}++

$ perl -E'
    sub DESTROY {}
    sub AUTOLOAD { say "$AUTOLOAD @_"; bless {} }
    tie %h, main;
    $h{a}++;
'
main::TIEHASH main
main::FETCH main=HASH(0x7fb6c982a188) a
main::STORE main=HASH(0x7fb6c982a188) a 140423041558889

这也有望处理嵌套 case $h{a}{b}++,但是我无法弄清楚为什么,最重要的是,如何覆盖此行为:

$ perl -E'
    sub DESTROY {}
    sub AUTOLOAD { say "$AUTOLOAD @_"; bless {} }
    tie %h, main;
    $h{a}{b}++;
'
main::TIEHASH main
main::FETCH main=HASH(0x7fbff102a188) a

我在测试Tie::CHI时偶然发现了这一点。它显然能够存储复杂的对象:

$ perl -MDateTime -MTie::CHI -E'
    tie %c, "Tie::CHI", { driver => "File", root_dir => "." };
    $c{a} = DateTime->now;
'

Perl 能够从深度嵌套的结构中检索任何数据,此外:

print Dumper $c{json}->{results}[0]{geometry}{location};

但是在嵌套结构中存储在任何 tie() 的哈希中都不起作用:

$c{json}->{results}[0]{geometry}{location} = [0, 0];

可以修补 Tie::CHI 以使用更多 DWIMmery 处理这种情况吗?如果没有,有什么替代方案?

4

2 回答 2

4

你是否意识到

$h{a}{b}

$h{a}->{b}

那是由两个单独的哈希查找组成的吗?基本上是一样的

my $anon = $h{a};
$anon->{b}

您想%{ $h{a} }成为一个已绑定的哈希,但$h{a}( FETCH) 返回了一个对未绑定哈希的引用。更改它以返回绑定的哈希。

$ perl -E'
    sub DESTROY {}
    sub FETCH { say "FETCH @_"; tie my %h, main; \%h; }
    sub AUTOLOAD { say "$AUTOLOAD @_"; bless {} }
    tie %h, main;
    $h{a}{b}++;
'
main::TIEHASH main
FETCH main=HASH(0x8006c030) a
main::TIEHASH main
FETCH main=HASH(0x80071e28) b
main::TIEHASH main
main::STORE main=HASH(0x80071e28) b 2147952185
于 2013-02-02T16:42:32.937 回答
1

正如 ikegami 的回答所得出的那样,要在Tie::CHI中正确实现嵌套的HashRefs ,有必要创建一个递归转换器,该转换器遍历使用接口包装散列/数组引用的数据结构。一点都不酷。tie()

幸运的是,有不止一种方法可以做到这一点,DBM::Deep将自己展示为整个CHI命名空间的坚如磐石的替代品。

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;
use DBM::Deep;

tie my %c, 'DBM::Deep', 'test.db';

$c{json}->{results}[0]{geometry}{location} = [0, 0];
print Dumper \%c;

通过将每个引用封装为DBM::Deep::(Array|Hash)

$VAR1 = {
    'json' => bless( {
            'results' => bless( [
                    bless( {
                            'geometry' => bless( {
                                    'location' => bless( [
                                            '0',
                                            '0'
                                        ], 'DBM::Deep::Array' )
                                }, 'DBM::Deep::Hash' )
                        }, 'DBM::Deep::Hash' )
                ], 'DBM::Deep::Array' )
        }, 'DBM::Deep::Hash' )
};

而且,除了::File引擎,DBM::Deep 也支持::DBI引擎。

于 2013-02-03T02:37:27.680 回答