> On 17 Nov 2017, at 20:09, Fernando Santagata <nando.santag...@gmail.com> 
> wrote:
> I tried to use the code you suggested:
> 
> sub trait_mod:<is>(Attribute:D \attribute, :&proxy!) {
>   attribute.package.^add_method(attribute.name, my method () { proxy($_) })
> }
> 
> class A {
>   has $!a is proxy({ $^a * 2 });
>   has $!b is proxy({ $^a * 3 });
> }
> 
> my A $a .= new;
> $a.a = 21;    # <-- No such method 'a' for invocant of type 'A'
> say $a.a;
> $a.b = 21;
> say $a.b;
> 
> But I got an error on the first assignment.
> What am I doing wrong?

Ok, finally had some time to figure this out more deeply.  My result:
=====================================
sub trait_mod:<is>(Attribute:D \attribute, :&proxy!) {
    my $name   = attribute.name;
    my $method = $name.substr(2);
    attribute.package.^add_method($method, my method ($SELF:) is raw {
        use MONKEY-GUTS;
        Proxy.new(
          FETCH => { nqp::getattr(nqp::decont($SELF),$SELF.WHAT,$name) },
          STORE => -> $, $value {
            nqp::bindattr(nqp::decont($SELF),$SELF.WHAT,$name,proxy($value))
          }
        )
    });
}

class A {
      has $!a is proxy({ $^a * 2 });
      has $!b is proxy({ $^a * 3 });
}

my A $a .= new;
$a.a = 21;    
say $a.a;   # 42
$a.b = 21;
say $a.b;   # 63
=====================================

Unfortunately, this involves some MONKEY guts…  lemme see if I can figure out a 
way for you not to have to do that.



Liz

Reply via email to