This may all be explained in the upcoming A12, but I'm trying to get Accessors figured out in my head, and I had a few questions and comments.
===== paraphrased from Damian in http://www.nntp.perl.org/group/perl.perl6.language/9576) it seems very likely that if you write: class Foo { # version 1 has $.bar_attr is public; } then you'll get an automagically created lvalue accessor method that will allow you to write: my $foo = Foo.new(); $foo.bar_attr = 1; and then later define a real C<Foo::bar_attr> method to encapsulate it: class Foo { # version 2 has $.bar_attr is public; method bar_attr is rw($rvalue) () { if exists $rvalue { croak "Negative value" if $rvalue < 0; $.bar_attr = $rvalue; } return $.bar_attr; } } ===== >From Damian's comments I conclude: There will be one autogenerated accessor, with the same name as the attribute (not get/set pairs). It will work correctly in all these cases: $x = $foo.bar_attr; # read $foo.bar_attr = $x; # write $x = $foo.bar_attr = $y; # write then read My question is about these cases: $foo.bar_attr += $z # read then write $foo.bar_attr++; L<Apocalypse 6/Lvalue subroutines> would seem to apply here because of the "is rw" trait. It says I will need to return a proxy object in order for these cases to work right, because I only get to return from the accessor once, and subsequent writes are performed on the proxy object. In fact, I think Damian's example above (written long before A6, so not his fault) would fail to croak if I wrote: $foo.bar_attr = 12; $foo.bar_attr -= 100; According to A6, it should probably be written like this: method bar_attr() is rw { return my $bar_proxy is Proxy( for => $.bar_attr, STORE => { croak "Negative value" if $_ < 0; $.bar_attr = $_; }, ); } But if we *always* have to return a proxy object, in case someone uses += on our attribute, I can see users yearning for the simplicity of get/set, even if it is not as syntactically sweet. I really like the "is Proxy" for tie-ing things, but I keep thinking its a bit of overkill for accessors. From an easy-things-should-be-easy perspective, I wouldn't mind at all if $object.attr += 3 magically arranged to call an accessor twice: once to read, and once to write. The accessor would have a simple signature: method bar(?$val) {...} It is simple to know if the accessor is reading or writing: method bar(?$val) { print "Ima reader" if want; print "Ima writer" if exists $val; } But I am asking for magic with that, because $foo.bar is no longer what it looks like (a method with no arguments). "$foo.bar += 3" is transformed into "$for.bar($foo.bar() + 3)". I may lose things like the ability to bind, etc. A proxy should be able to do anything, it just doesn't do it as simply as I want. So it occurs to me that it might be possible to implement the one in terms of the other. To do that I need to explore another area from the upcoming apocalypse (traits), so forgive my deficient syntax. 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'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 : ) { # "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; # wrap the applyee $acc.wrap( sub (?$val) { $proxy = $val if exists $val; # so $foo.bar(1) still works return $proxy; } ); } } 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