Done a bit of noodling about this morning and I got this. And it works....
sort of.
.perl calls the get_value method but the accessor and private value reads
don't. (I'm guessing this is what you came up against Vadim?)
Still the self deleting wrapper is a fun trick. Best I do some work now
though.
use v6.c;
role LazyAttr {
has $.get-wrapper is rw;
}
multi sub trait_mod:<is> ( Attribute $a, :@lazy [ &builder ] ) {
$a does LazyAttr;
$a.set_build(
-> |c {
$a.get-wrapper = $a.^find_method('get_value').wrap(
-> $self, $instance {
my $val = &builder( $instance );
$a.set_value( $instance, $val );
$a.get-wrapper.restore;
$val;
}
);
Any;
}
);
}
class Test {
sub build-a( $self ) { note "Build A Called"; sleep 1; 5 }
sub build-b( $self ) { note "Build B Called"; sleep 2; 10 }
has $.a is lazy[&build-a];
has $.b is lazy[&build-b];
}
my $t = Test.new();
say $t.perl;
On Wed, 5 Sep 2018 at 23:45 Vadim Belman <[email protected]> wrote:
> Looking forward to see what you come up with. I do mix in a role into both
> Attribute and ClassHOW. But delving into the core didn't help to find a
> better approach than the one I finally took. Two subtle aspects are to be
> kept in mind: support for roles; and knowing the object attribute is
> belonging to.
>
> > So I have a thought for how to do lazy attributes without Proxy objects.
> It is late so I'll try and poke about at it tomorrow but I think we can
> Mixin a role to the Attribute using a trait.
> >
> > The role will track if the attribute was set to a value at build and if
> not call a block it's given when first read from. This gets round the issue
> of if we want to set it to Any.
> >
> > I *think* this will work. The stuff I've been doing with Trait::Env
> would point that way.
> >
>
> Best regards,
> Vadim Belman
>
> --
Simon Proctor
Cognoscite aliquid novum cotidie