0

解析して読み取る必要がある php-ini-file がありますConfig::IniFiles。この ini ファイルには、他のセクションから設定を継承するセクションがあります。構造は次のようになります。

[section1]
...
...
[section2:section1]
...
...
[section3:section2]
...
...

等々。

ここで、 からキーの値を読み取りたい場合section3、オブジェクトは undef を返します。これは、セクションしか認識していないためsection3:section2です。すでに予想されているかもしれませんが、これは継承の望ましい動作ではありません。私の場合、オブジェクトが最初に から値を読み取ろうとしsection3、そこに値が見つからない場合は、試してから を試してみたいと思いsection2ますsection1。このモジュールでこれを達成する方法はありますか、それともラッパーモジュールを作成してこの機能を自分で実装する必要がありますか?

4

1 に答える 1

2

構成の継承を実装する 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);
};

入力に使用されるデータ構造がセクションの順序を記憶できる場合、この深さ優先のソリューションはさらに簡単になります。ただし、ハッシュは順不同です。

于 2013-09-12T08:47:43.493 に答える