2017-08-14 19 views
5

は、この単純化しすぎXMLファイルを考えるとあなたがfooの値がNilであることがわかりますオブジェクト属性に値が設定されていないのはなぜですか?</p> <blockquote> <pre><code><Foo>Bar</Foo> </code></pre> </blockquote> <p>そして<code>Foo</code>要素の値を抽出し、このコード:

use XML::Rabbit; 
use Data::Dump::Tree; 

class RunInfo does XML::Rabbit::Node { 
    has $.foo is xpath("/Foo"); 
} 

sub MAIN ($file!) { 

    my $xml = RunInfo.new(file => $file); 

    dump $xml; 

    put "-----------------------"; 
    put "Foo is $xml.foo()"; 
} 

を、出力はFoo is Barと表示されますが、

.RunInfo @0 
├ $.foo = Nil 
├ $.context is rw = .XML::Document @1 
│ ├ $.version = 1.0.Str 
│ ├ $.encoding = Nil 
│ ├ %.doctype = {0} @2 
│ ├ $.root = .XML::Element @3 
│ │ ├ $.name is rw = Foo.Str 
│ │ ├ @.nodes is rw = [1] @4 
│ │ │ └ 0 = .XML::Text @5 
│ │ │ ├ $.text = Bar.Str 
│ │ │ └ $.parent is rw = .XML::Element §3 
│ │ ├ %.attribs is rw = {0} @7 
│ │ ├ $.idattr is rw = id.Str 
│ │ └ $.parent is rw = .XML::Document §1 
│ ├ $.filename = example.xml.Str 
│ └ $.parent is rw = Nil 
└ $.xpath is rw = .XML::XPath @9 
    ├ $.document = .XML::Document §1 
    └ %.registered-namespaces is rw = {0} @11 
----------------------- 
Foo is Bar 

(免責事項:私は私のコードでは、今日、この動作に出くわしたので、私はQ &スタイルをそれを書きました。その他の回答はようこそ)。

ところで、ここにはXML::RabbitData::Dump::Treeへのリンクがあります。

答えて

2

これは結果ではありません組み込みのPerl 6の機能ではなく、むしろ何かXML::Rabbitモジュールがあります。

そのモジュールは特性を提供し、クラス構成時に、その特性が適用されている属性がカスタムメソッドでオーバーライドされたアクセサメソッドを取得するようにします。

カスタムアクセサメソッドは、最初に呼び出されたときに属性の値を計算して設定します。後続の呼び出しでは、属性に既に格納されている値が返されます。 (省略さ部品とthe module's source codeから採取された)次のように

カスタムアクセサメソッドが実装されている:ここ

method (Mu:D:) { 
    my $val = $attr.get_value(self); 
    unless $val.defined { 
     ... 
     $val = ...; 
     ... 
     $attr.set_value(self, $val); 
    } 
    return $val; 
} 

$attr属性に対応Attributeオブジェクトであり、方法をインストールする前に取得されましたMeta-Object Protocol (MOP)を使用してください。


Data::Dump::Treeモジュールは、順番に、属性の値を取得するためにアクセサメソッドを使用するのではなく、MOPを使用して、それを直接読み込んでいません。

したがって、アクセサがまだ呼び出されていないため、属性の値がまだ設定されていない場合は、Nilと表示されます。

4

これはPerl 6の多くのものと同様に、lazyです。言い換えれば、あなたが要求しない限り、意図的にfooの属性を把握するのに時間を費やすことはありません。これは、必要がない限り計算リソースを消費するのを避ける最適化です。

あなたがfooメソッドを呼び出した後のデータ構造をダンプする場合は、それがデータ・ダンプに移入されていることがわかります:

use XML::Rabbit; 
use Data::Dump::Tree; 

class RunInfo does XML::Rabbit::Node { 
    has $.foo is xpath("/Foo"); 
} 

sub MAIN ($file!) { 

    my $xml = RunInfo.new(file => $file); 

    put "Foo is $xml.foo()"; 

    dump $xml; 
} 
Foo is Bar 
.RunInfo @0 
├ $.foo = Bar.Str 
├ $.context is rw = .XML::Document @1 
│ ├ $.version = 1.0.Str 
│ ├ $.encoding = Nil 
│ ├ %.doctype = {0} @2 
│ ├ $.root = .XML::Element @3 
│ │ ├ $.name is rw = Foo.Str 
│ │ ├ @.nodes is rw = [1] @4 
│ │ │ └ 0 = .XML::Text @5 
│ │ │ ├ $.text = Bar.Str 
│ │ │ └ $.parent is rw = .XML::Element §3 
│ │ ├ %.attribs is rw = {0} @7 
│ │ ├ $.idattr is rw = id.Str 
│ │ └ $.parent is rw = .XML::Document §1 
│ ├ $.filename = example.xml.Str 
│ └ $.parent is rw = Nil 
└ $.xpath is rw = .XML::XPath @9 
    ├ $.document = .XML::Document §1 
    └ %.registered-namespaces is rw = {0} @11 
関連する問題