You could probably do this nicer as an Addtribute trait:

Creator.pm
==========
sub trait_mod:<is>(\attribute, :&proxy!) is export {
    attribute.package.^add_method(attribute.name,my method () { proxy($_) })
}

A.pm
====
use Creator;

class A {
    has $!a is proxy( &func );
    has $!b is proxy( &func );
}

Didn’t test this thoroughly, but this should give you some idea.  :-)


Liz

> On 16 Nov 2017, at 10:31, Fernando Santagata <nando.santag...@gmail.com> 
> wrote:
> 
> Maybe someone might find this useful.
> 
> In the end I concocted this kind of code. The price of simplicity at the base 
> program level is paid at the class level, with a specific BUILD submethod, 
> and with an even greater complexity at role level, where the accessors are 
> created dynamically with some metaprogramming.
> 
> role Creator {
>   method create(::class, $method, $attribute is rw, &func) {
>     ::class.^add_method($method, my method (::class:) {
>       Proxy.new(
>         FETCH => { $attribute },
>         STORE => -> $, $value { $attribute = &func($value) }
>       )
>     });
>   }
> }
> 
> class A does Creator {
>   has $!a;
>   has $!b;
>   submethod BUILD {
>     self.create(::A, 'a', $!a, { $^a * 2 });
>     self.create(::A, 'b', $!b, { $^a * 3 });
>   }
> }
> 
> my A $a .= new;
> $a.a = 21;
> say $a.a;  # 42
> $a.b = 21;
> say $a.b;  # 63
> 
> 
> On Tue, Nov 14, 2017 at 7:09 PM, Elizabeth Mattijsen <l...@dijkmat.nl> wrote:
> This might it then:
> 
> class A {
>     has $!a;  # $.a if you want to be able to assign with .new
>     method a() {
>         Proxy.new(
>           FETCH => { $!a },
>           STORE => -> $, $value { $!a = $value * 2 }
>         )
>     }
> }
> my $a = A.new;
> $a.a = 77;
> dd $a.a;   # 154
> 
> > On 14 Nov 2017, at 18:51, Fernando Santagata <nando.santag...@gmail.com> 
> > wrote:
> >
> > Hi Liz,
> >
> > What I need is to preprocess the value before assigning it to an attribute.
> >
> > I would do that in Perl5/Moose, using "around", like this:
> >
> > package A;
> > use Moose;
> >
> > has 'attribute' => (is => 'rw', isa => 'Str');
> >
> > around [qw(attribute)] => sub {
> >   my ($next, $self, $val) = @_;
> >   return $self->$next unless $val;
> >   return $self->$next(preprocess $val); # Preprocess the value before the 
> > assignment
> > }
> >
> > In this way I don't have to make an explicit call to the preprocessor any 
> > time I assign a value to that attribute, effectively removing that from the 
> > main program.
> >
> > I'm looking for a way to do that in Perl6.
> >
> > On Tue, Nov 14, 2017 at 6:11 PM, Elizabeth Mattijsen <l...@dijkmat.nl> 
> > wrote:
> > > On 14 Nov 2017, at 18:06, Fernando Santagata <nando.santag...@gmail.com> 
> > > wrote:
> > > I'm converting a program from Perl5/Moose.
> > > I have several classes, each has some attributes that need to be 
> > > processed in the same way before being passed to other objects.
> > >
> > > When I was using Moose, I had some "around" methods that would 
> > > automatically modify the value before delivering it to those attributes, 
> > > so delegating the object to do the needed adjustments.
> > >
> > > Stripped to the bare bones, the thing that in Perl6 looks like this:
> > >
> > > class A {
> > >   has $!a;
> > >
> > >   method a($val?)
> > >   {
> > >     if $val.defined {
> > >       # Modify $val in some way
> > >       $!a = $val;
> > >     } else {
> > >       $!a;
> > >     }
> > >   }
> > > }
> > >
> > > my A $a .= new;
> > > # $a.a = 42; # This outputs an error
> > > $a.a(42);
> > > say $a.a;
> > >
> > > Any hint how to make it work as an assignment, instead of a method call?
> > > Better yet, is there a way to abstract that behavior in a role?
> >
> > I think you want “is rw” on a public attribute?
> >
> > class A {
> >     has $.a is rw;
> > }
> > my $obj = A.new;
> > $obj.a = 42;
> > dd $obj;
> > ===========
> > A $obj = A.new(a => 42)
> >
> >
> >
> > Liz
> >
> >
> >
> > --
> > Fernando Santagata
> 
> 
> 
> -- 
> Fernando Santagata

Reply via email to