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 

Reply via email to