鉴于这个过于简化的XML文件:
<Foo>Bar</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 );
dump $xml;
put "-----------------------";
put "Foo is $xml.foo()";
}
即使输出显示foo
,您也会看到Nil
的值为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&amp; A风格。欢迎其他答案。)。
顺便说一下,这里有指向XML::Rabbit和Data::Dump::Tree的链接。
答案 0 :(得分:4)
它是lazy,就像Perl 6中的许多内容一样。换句话说,它有意不会浪费时间来确定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
答案 1 :(得分:2)
这不是内置Perl 6功能的结果,而是 XML::Rabbit
模块的功能。
该模块提供is xpath
特征,并确保在类组合时,任何具有该特征的属性都会使用自定义方法覆盖其访问方法。
自定义访问器方法在第一次调用时计算和设置属性的值,并且在后续调用中只返回现在已存储在属性中的值。
自定义访问器方法实现如下(取自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直接读取它。 / p>
因此,如果尚未设置因为尚未调用访问者,它会将属性的值视为Nil
。