構成の継承を実装する Perl モジュールが見つかりません。
しかし、継承を処理する単純なフィルターを作成することはそれほど複雑ではありません。HoH を指定すると、構成内の各エントリがデルタとして表示される場合、次のように継承を解決できます。
use Algorithm::C3; # must be installed from CPAN
sub resolve_inheritance {
my $input = shift;
my %output;
# hash of arrays where the arrays contain all parents
my %child_parent_relations =
map { my ($c, @p) = split /\s*:\s*/; $c => [\@p, $input->{$_}] } keys %$input;
my $get_parents = sub { @{ $child_parent_relations{shift()}[0] } };
my $get_data = sub { $child_parent_relations{shift()}[1] };
# prepare stuff for C3 resolution
my $resolution_cache = {};
my $resolve = sub {
my $child = shift;
Algorithm::C3::merge($child, $get_parents, $resolution_cache);
};
# now we go through all childs, and build temporary hashes from the C3 linearization.
for my $child (keys %child_parent_relations) {
my @linearization = $resolve->($child);
my %temp;
for my $delta_name (reverse @linearization) {
my $delta = $get_data->($delta_name);
@temp{keys %$delta} = values %$delta;
}
# save the data in the output:
$output{$child} = \%temp;
}
return \%output;
}
テスト:
my $input = {
's1' => { A => 1 },
's2:s1' => { A => 2, B => 2 },
's3:s1' => { B => 3, C => 3 },
's4:s3:s2' => { }
};
my $expected = {
's1' => { A => 1 },
's2' => { A => 2, B => 2 },
's3' => { A => 1, B => 3, C => 3 },
's4' => { A => 2, B => 3, C => 3 },
};
use Test::More tests => 1;
is_deeply resolve_inheritance($input), $expected, 'C3 resolution';
ご覧のとおり、これにより:
-operator に右結合性 (右から左へ結合) が与えられます。
深さ優先の解像度が必要な場合、つまり:
my $expected = {
's1' => { A => 1 },
's2' => { A => 2, B => 2 },
's3' => { A => 1, B => 3, C => 3 },
's4' => { A => 1, B => 3, C => 3 }, # s3 completely overwrites s2
};
すると、別の結果が得られます。これは、最初に各親を継承してから、階層全体ではなく直接の親のみを結合することで実行できます。単一継承の場合、深さ優先線形化と C3 解決の結果は同等です。
深さ優先の解決をサポートするために$resolve
、上記のコードの関数を交換し、次のように変更します。
my $resolve; $resolve = sub {
my $child = shift;
return $child, map { $resolve->($_) } $get_parents->($child);
};
これは最小限の変更ですが、もちろん、各親の左端のオカレンスのみを保持することで、より効率的にすることができます:
use List::MoreUtils 'uniq';
my $resolve; $resolve = sub {
my $child = shift;
return uniq $child, map { $resolve->($_) } $get_parents->($child);
};
入力に使用されるデータ構造がセクションの順序を記憶できる場合、この深さ優先のソリューションはさらに簡単になります。ただし、ハッシュは順不同です。