Here is a quickly hacked together example:
multi trait_mod:<is> (Attribute:D $a, :$xmlattr!) {
my $mname = $a.name.substr(2);
my &method = my method { say "ATTR($mname):", my \val = $a.get_value(self);
val };
&method.set_name($mname);
$a.package.^add_method($mname, &method);
}
class Foo {
has $.foo is xmlattr;
}
say Foo.new(foo => 42).foo;
It would output:
ATTR(foo):42
42
Best regards,
Vadim Belman
> On Sep 8, 2019, at 8:59 PM, Mark Devine <[email protected]> wrote:
>
> Vadim,
>
> Vadim,
>
> Would you be able to expand on how to implement the trait that wraps into
> what is effectively the ‘get_value’ accessor of an attribute? I’m not
> finding enough in the documentation to connect the dots. I’ve looked at
> XML::Class, which does some pretty heavy trait’ing, but my intuition has
> expired.
>
> my role XML-attribute {
> has $attr;
> method get_value () {
> say 'in XML-attribute method get_value with ' ~ $.name;
> $attr;
> }
> method set_value ($) {
> say 'in XML-attribute method set_value with ' ~ $.name;
> $attr = $;
> }
> }
>
> multi sub trait_mod:<is> (Attribute $a, :$xmlattr) {
> say "⟨is xmlattr⟩ has been called with ⟨$xmlattr⟩ on {$a.WHICH}";
> $a does XML-attribute;
> }
>
> class System {
> has Str $.SerialNumber is xmlattr;
> }
>
> say System.new(:SerialNumber('ABCDEFG')).SerialNumber;
>
>
> I’ve twisted myself into a pretzel. I couldn’t even find where a role gets
> ‘$’, but I saw it in JSTOWE’s code so I mimicked.
>
> I need a little more broad-based help on what goes where and when.
>
> Thanks,
>
> Mark
>
> From: Vadim Belman <[email protected]>
> Sent: Sunday, September 8, 2019 14:57
> To: Mark Devine <[email protected]>
> Cc: perl6-users <[email protected]>
> Subject: Re: Wrap an attribute’s ^get_value method in TWEAK
>
> Hi Mark,
>
> get_value won't give you what you expect. It's use is narrowly limited to
> trait 'is handles' and method .perl. Besides, are you sure all of your
> attributes will be considered as belonging to XML? I mean, won't there be
> need for utility attributes serving exclusively internal needs of a class? If
> so, then the best solution is to create a trait for an attribute and have it
> like:
>
> has $.SerialNumber is xmlattr;
>
> The trait would then install an accessor which would do what you need.
>
> Best regards,
> Vadim Belman
>
>
> On Sep 8, 2019, at 12:41 PM, Mark Devine <[email protected]
> <mailto:[email protected]>> wrote:
>
> Perl6 Community,
>
> How do I properly wrap an attribute’s ^get_value method in TWEAK? If a
> condition exists, I’d like to wrap all (:local) attributes so that they can
> do some extra work.
>
> The module that I’m working on has classes/attributes for hundreds of fields
> in dozens of different, big XML files -- there’s a lot. And XML is easily
> extended, so I may very well be adding hundreds more attributes in the
> future. I would very much prefer to preserve the automatic accessor behavior
> of ‘has $.attr;’ versus writing a billion set/get accessors myself – truly
> prohibitive. Wrapping seems the elegant/extensible approach.
>
> class System {
> has $.SerialNumber;
> submethod TWEAK {
> for self.^attributes(:local) -> $attr {
> self.$attr.^get_value.wrap: { say 'in ' ~ $attr.name ~ "'s
> get_value"; nextsame; };
> }
> self;
> }
> }
> say System.new(:SerialNumber('ABCDEFG')).SerialNumber;
>
> # OUTPUT: No such method 'CALL-ME' for invocant of type 'Attribute'
>
> I know the above .wrap is probably misguided, but it sort of demonstrates
> what I’m trying to do.
>
> I’m not finding the proper approach. Any hints? Any tutorials? Any
> existing examples in the ecosystem that I could mimic?
>
> Thanks,
>
> Mark