Why is my object attribute not populated?

Given this simplified XML file:

<Foo>Bar</Foo> 

And this code that retrieves the value for the Foo element:

 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()"; } 

You will see that the value for Foo is Nil , although Foo is Bar displayed in the output:

 .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 

(Disclaimer: I came across this behavior today in my code, so I wrote it in the style of Q and A. Other answers are welcome.).

By the way, here are the links to XML :: Rabbit and Data :: Landfill :: Tree .

+5
source share
2 answers

This is not the result of the Perl 6 built-in function, but rather the XML::Rabbit module.

This module provides the is xpath attribute and ensures that during the compilation of a class, any attribute that applies this attribute receives its access method, overridden with a custom one.

The user access method calculates and sets the value for the attribute on the first call, and on subsequent calls, it simply returns the value already stored in the attribute.

The user access method is implemented as follows (taken from the source code of the module with details):

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

Here $attr is the Attribute object corresponding to the attribute, and was retrieved before the method was installed using the Metaobject Protocol (MOP) .


The Data::Dump::Tree module, in turn, does not use the accessor method to retrieve the attribute value, but reads it directly using the MOP.

Therefore, he sees the value of the attribute as Nil , if it is not already set, because the accessor has not yet been called.

+2
source

This is lazy , like so many things in Perl 6. In other words, it intentionally doesn't waste time figuring out what the foo attribute is unless you ask it about it. This is an optimization that avoids the use of computing resources if you do not need them.

If you unload the data structure after calling the foo method, you will see that it is entered in the data dump:

 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 
+4
source

Source: https://habr.com/ru/post/1270861/


All Articles