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

Reply via email to