On 4/19/04 7:20 PM, Larry Wall wrote:
> On Mon, Apr 19, 2004 at 06:53:29PM -0400, John Siracusa wrote:
> : Yeah, that's exactly what I don't want to type over and over :)
>
> I really don't understand what you're getting at here. First you
> complain that you'd rather write an ordinary method, and then you
> complain that you have to. Have I met someone lazier than me? :-)
Possibly :) Here's what I'm saying. In the first version of a class, there
will probably be a lot of simple get/set attributes. It's convenient not to
have to write any explicit methods for those.
If I accept the default accessors that you get "for free" when a class "has
$.foo is rw", then that means the users of my class can do $obj.foo =
whatever in order to set the foo attribute.
That's fine...until, some day down the road, I decide that getting and/or
setting the foo attribute needs to do something a bit more complex. Or
maybe I remove the $.foo attribute all together and replace it with a
collection of other attributes or something.
I can do that by writing my own foo() method, but there's the problem of all
the existing code out there that says $obj.foo = whatever. In order to
continue to support that, I have to provide an lvalue. As has been pointed
out, I can use "will STORE" to add the "extra" behavior while continuing to
use $.foo (or a proxy object, yadda) as my lvalue. But I find that slightly
kludgy.
If the default accessor had instead been defined like (the Perl 6
equivalent) of this:
sub name { @_ > 1 ? $_[0]->{'foo'} = $_[1] : $_[0]->{'foo'} }
then I wouldn't have any existing code doing $obj.foo = whatever to worry
about. So extending my foo() accessor by writing my own method would be
straight-forward.
Another alternative is to have a simpler, more direct way to continue to
support the $obj.foo = whatever semantics by writing a particular kind of
foo() method. I don't like piling the "side effects" into a "will STORE"
trait, since in version 4.0 of my class there could be a ton of code hanging
off that hook. It just looks like the wrong place to put that. I'd rather
have all the fancy things done when I call $obj.foo() defined in method foo
{ }.
A final alternative is to never use the default accessor that I get when my
class "has $.foo is rw" because that means having to support $obj.foo =
whaever semantics forever and ever. But that means I have to write (the
Perl 6 equivalent of) this:
sub name { @_ > 1 ? $_[0]->{'foo'} = $_[1] : $_[0]->{'foo'} }
for every single attribute. That's tiresome.
Basically, I'm wondering exactly who is the target audience for the default
accessor? It seems to tie the API to a very confining set of behaviors, and
expose more of the internals of a class than I'd like.
If $ob.foo will really never expand beyond a simple get/set interface to an
attribute, it works fine. But that's rarely true in the long term, IME. It
also, I think, creates an artificial distinction between those "simple"
attributes that users can expect to set with $obj.foo = whatever, and the
more complex attributes that must be set with $obj.foo(whatever). I'd like
more symmetry in my APIs, but then I'm faced with the options describe
above, none of which are as appealing as I'd like.
I think others will also value API symmetry and will therefore either create
their own "old-style" accessors everywhere, or (more likely) go to heroic
measures to support $obj.foo = whatever everywhere, forever, probably by
dangling 80% of their attribute accessor methdod code off of "will STORE"
hooks by the time version 4.0 cof their class rolls around. That's not
pleasant, IMO.
-John