John Williams writes: > I want to get from here > > method bar_attr(?$val) is accessor { > $.bar_attr = $val if exists $val; > return $.bar_attr; > } > > to here > > method bar_attr() is rw { > return my $x is Proxy ( > for => $.bar_attr, > FETCH => { $.bar_attr }, > STORE => { $.bar_attr = $_ }, > ); > } > > using a break-the-rules trait called accessor.
I think this is a good idea. Proxies are a little advanced for someone who, say, comes from C# and doesn't understand tying yet. I think you're going about it wrong, though. Here's how I imagine this working: method bar_attr() will access -> $self: ?$val { $.bar_attr = $val if exists $val; return $.bar_attr; } Or, alternatively: method bar_attr() will get { $.bar_attr } will set { $.bar_attr = $_ } And the traits C<access>, C<get>, and C<set> define C<do> to do the right thing. The only trickyness that I see is getting C<get> and C<set> to work together, since they each need to define part of the same proxy class. > I'm not sure what method gets called when a trait is applied to something, > so I will assume that APPLY is called with the something it is applied to > as the invocant. > > trait accessor { > my $proxy is Proxy; > > method APPLY( Code $acc : ) { I don't think that's right. That means, to apply the trait, you call this way: &bar_attr.accessor::APPLY; Where I would think it would be something more like: accessor.APPLY(&bar_attr); Implying a signature like: method APPLY(Code $acc is rw) {...} > # "Proxy" is a trait/role with FETCH and STORE attributes (?) > $proxy.FETCH = { $acc() }; > $proxy.STORE = { $acc($^a) }; > # Proxy.for is not set, since I do not know what is being > # proxied; I only know how to access it. > > # add the rw trait > $acc but= rw; C<rw> is a trait, not a role. So you can't C<but> it on. Probably. > # wrap the applyee > $acc.wrap( sub (?$val) { > $proxy = $val if exists $val; # so $foo.bar(1) still works > return $proxy; > } ); > } > } That looks okay to me, little as I know about traits. I'm a little uneasy about declaring the Proxy as a lexical in trait scope; I'd be inclined to declare it as a lexical in the C<APPLY> routine, or even in the anonymous sub that you're wrapping with. Luke > I *think* that accomplishes my goal of simple-to-write accessors (for > scalars, at least). Now I only have to change the signature in Damian's > example, and I think it will work for $foo.bar_attr -= 9999999; > > method bar_attr(?$rvalue) is accessor { > if exists $rvalue { > croak "Negative value" if $rvalue < 0; > $.bar_attr = $rvalue; > } > return $.bar_attr; > } > > Or maybe I'm missing the point completely.... comments? rebuttals? > > ~ John Williams > >