On Tue, 20 Apr 2004, Brent 'Dax' Royal-Gordon wrote:
> John Williams wrote:
> > I'm not saying there is anything wrong with that, but John Siracusa is
> > asking for something different, I think. A simple accessor which looks
> > like a method without having to play with Proxy, FETCH, STORE, etc.
> > If it still looks like $obj.foo = 1 outside the class, that's good too.
> > (Delphi and C# can do it; why can't we?)
>
> C# does it as
> ...
Interesting. Here's the Delphi version, for comparison.
// the trivial attibute
SomeNumber : Integer;
// the virtual property
// read/write can refer to either a variable or a func/proc
property VirtWrite : Integer read SomeNumber write SetSomeNumber;
procedure SetSomeNumber( in : Integer );
function GetSomeNumber : Integer;
The big win being that one can replace the trivial attribute with a
property, and the interface stays the same.
The perl6 version of that would of course be
class Dog {
method getfoo returns Int {...};
method setfoo(Int $v) {...};
has Int $.foo will FETCH \&getfoo
will STORE \&setfoo;
}
I'm not saying there is anything wrong with that. I completely agree with
Larry that the correct interface for accessors is $x = $obj.foo = $y;
I'm mainly curious if there is an even simpler way to define the
implementation of the accessor than the above.
The simplest possible rw accessor is
method foo is rw { $.foo };
which basically just makes $.foo available to the outside. When you get
more complex and need to intercept the reading and writing, it's clear
that returning a Proxy object is the best way (so far proposed) to do the
right thing for ($x = $obj.foo = $y) and ($obj.foo++). For convenience
and to avoid being uncool-retro, one also wants to separate the accessor
into read and write multi methods.
multi method foo() returns Int {...};
multi method foo(Int $v) {...};
has Int $.foo will FETCH { .foo } # ignore the name conflict for now
will STORE { .foo($^value) };
The declaration of the "has" variable to delegate to the above methods now
becomes repetitive boilerplate code, which could be eliminated by a clever
trait. It also interferes with the obvious name for a multi method
reader.
foo() obviously works fine (by itself) as a reader, but foo($) needs some
help. Somehow foo() has to return a Proxy which delegates STOREs to
foo($), and FETCHes to itself. Since foo() works fine as a read-only
accessor by itself, a minimalist approach shouldn't require foo() to add a
trait. foo($) needs the help so it should get the trait.
So I propose (in the request-for-comments sense, not the "this should
go into perl6 core" sense) that given a trivial accessor:
has $.foo is rw;
the minimal replacement with full read/write control would be this:
multi method foo() {...};
multi method foo($v) is accessor {...};
(And the accessor trait somehow does the magic to define a new foo() which
returns a Proxy which delegates to the declared foo() or foo($).)
~ John Williams