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

これもネストされたケースを処理することが期待され$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}

それは2つの別々のハッシュルックアップで構成されていますか?基本的には

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にネストされたHashRefを適切に実装する、データ構造をトラバースしてハッシュ/配列参照をインターフェイスでラップする再帰コンバーターを作成する必要があります。まったくクールではありません。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 に答える