John Siracusa writes:
> On 4/19/04 3:58 PM, Austin Hastings wrote:
> >> I initially decide to accept the default accessors.
> >> 
> >>     $dog.name = 'Ralph';
> >>     print $dog.age;
> >> 
> >> This works well for a while, but then I decide to update Dog so that setting
> >> the name also sets the gender.
> >> 
> >>     $dog.name = 'Susie'; # also sets $dog.gender to 'female'
> >> 
> >> How do I write such a name() method?
> >
> > has $.name is rw
> > will STORE { .set_name($^name); };
> 
> The "will STORE" stuff covers the easy cases, but can I extend it all the
> way up to a name() that's a multimethod with a ton of optional args?  I
> supposed you can (technically) do all of that with "will STORE", but it
> seems an odd place for what would more naturally be code in the name()
> method itself.

I think a role on the attribute is not the right place to put it.  What
you're doing is returning a proxy object that knows how to set both the
name and the gender.  Here are a couple of implementations:

    class Dog {
        has $.name;
        has $.gender;

        method name() {
            return my $dummy 
                is Proxy( 
                    for => $.name,
                    STORE => sub ($in) {
                        $.gender = /<Names::Female>/ ?? 'male' :: 'female';
                        $.name = $in;
                    },
                );
        }
    }

Yuck.  Much nicer:

    class Dog {
        has $.name;
        has $.gender;

        method name()
            will get { $.name }
            will set -> $in { 
                $.gender = /<Names::Female>/ ?? 'make' :: 'female';
                $.name = $in;
            }
        { }
    }

This is nothing new.  So, for fun, here's the implementation of C<get>
and C<set>:

    role get {
        multi sub trait_auxiliary:is(get $trait, &code: ?$arg) {
            wrap &code: {
                my $result := call;
                return my $dummy
                    is Proxy(
                        for => $result,
                        FETCH => $arg,
                    );
            };
        }
    }

    role set {
        multi sub trait_auxiliary:is(set $trair, &code: ?$arg) {
            wrap &code: {
                my $result := call;
                return my $dummy
                    is Proxy(
                        for => $result,
                        STORE => $arg,
                    );
            };
        }
    }

Luke

Reply via email to