On 4/20/04 12:14 PM, Luke Palmer wrote: > Okay, well, I thought that my example did that, but apparently using > C<will get> and C<will set> is a little too complex... (my sentiments > are beginning to follow Larry's, in that I'm not sure you know what you > want -- perhaps you could give a hypotheical syntax?)
There are a couple of solutions, each with some syntax. Here they are, in no particular order: * Provide a second kind of default accessor class Foo; has $.foo is accessor; # or whatever, pick a name With that "has" line alone, you auto-magically get an accessor that works like this: $obj.foo # get value of $.foo $obj.foo(5) # set $.foo = 5 Why this is useful: It doesn't require you to write anything other than the "has" line, and it provides a clean, simple way to extend the foo() accessor later in the life of the class by actually writing a foo() method. Unlike the "is rw" default accessor, there's no fear that any code will exist that says $obj.foo = whatever. I also think it's a more sensible default than the "is rw" semantics (*unless* the solution below is implemented). Training people to use the default "is rw" accessors only to have to explain later about all the hoops they will have to jump through in order to maintain that API when the foo method gets more complex is not my idea of a good time. * Provide a simple(r) way to easily support the $obj.foo = whatever behavior in perpetuity for any method. There are a few ways this could be done. One suggestion was to somehow appropriately remap this: $obj.foo = 5; to this: $obj.foo(5); once foo() mutates from an "is rw" default accessor to a full-blown "method foo(...) { }" I briefly entertained this solution in one of my earlier posts, but I think it's not a good idea. It's a good description of the type of behavior I want, but I don't like futzing with infix:= in order to get it. Another solution is to have a way to tell method foo() to yank its arg out of the rvalue if called as an lvalue. I don't have any good ideas about this syntax, but here's the overview: # Version 1.0 class Foo; has $.foo is rw; ... $obj.foo; # get $obj.foo = 5; # set Then: # Version 4.0 class Foo; has $.foo; # or maybe $.bar or anything else method foo(?$arg) { # The magic happens in the line below $arg = the rvalue if(caller wants lvalue); # Do all sorts of crazy stuff, possibly involving $.foo, possibly not ... return something; # maybe $.foo, maybe not } $obj.foo; # get $obj.foo(5); # set $obj.foo = 5; # still works, equivalent to $obj.foo(5) All the code for maintaining the ability to do $obj.foo = whatever is in the foo() method itself. It's not hanging off the $.foo attribute, and there may no longer even be a $.foo attribute anymore. The fact that a $.foo attribute existed at all was an implementation detail in version 1.0 of class Foo, IMO. I think all of these solutions are simpler and cleaner than the STORE hooks, proxy objects, roles, and macros that have been suggested (all of which seem like they'd work, FWIW). -John