develooper Front page | perl.perl6.language | Postings from June 2005

Re: Magic mutators and my $var is Proxy( ... );

Thread Previous | Thread Next
From:
Luke Palmer
Date:
June 26, 2005 22:30
Subject:
Re: Magic mutators and my $var is Proxy( ... );
Message ID:
7ca3f01605062622302afb3771@mail.gmail.com
On 6/26/05, Sam Vilain <sam@vilain.net> wrote:
> So, we've got this "my $var is Proxy( ... )" construct in A06.
> Say you've got this class:
> 
>    class MagicVal {
>       has Int $.varies is rw;
> 
>       method varies returns Int is rw {
>         return my $var is Proxy ( :for($.varies),
>                                   :FETCH{ $.varies += 2 },
>                                   :STORE{ $.varies = $_ + 1 },
>                                 );
>       }
>    }
> 
> Firstly, would this be correct syntax?  In particular, what should
> I call $.varies inside the :FETCH and :STORE subs?  Would they close
> over $?SELF, too?

Yes, just like when you say `my $self = shift` in Perl 5.  $self is closed over.

> If they did, doesn't this mean that $var will be a new Proxy attribute
> every time that the attribute is read, and will have side effects?

Well, your implementation has side-effects whether or not it's a new
Proxy every time.

> Such as;
> 
>   my $foo = MagicVal.new();
>   $foo.varies = 5;    # sets to 6;
>   say $foo.varies;    # says 8
>   say $foo.varies;    # says 10

Yep.

>   my $var = $foo.varies;  # $var is proxy for attribute
>   say $foo.varies;    # says 12
>   say $var;           # says 14

Nope.  The `is Proxy` is a trait on the *container*.  The container
does not pass through scalar assignment.  If you bound using :=
instead in the first line of this quote, then the semantics you
describe would occur.
 
> It seems to me that the only time I'd want to actually return a
> Proxy object is when taking a reference to the fake attribute.  In
> all other situations, you'd simply want to dispatch to either an
> accessor or a mutator, depending on the context. 

That is precisely what will happen.  It falls out of the semantics of
tied containers.

> ie, I'd like the design of this feature to be sufficient that most
> of the time, the Proxy object need never be constructed, and instead
> the relevant closure could be bound to that method instead.

I expect that it might be possible to optimize away such a proxy
object in non-referential context.  The sub checks its context: if it
is lvalue, then it immediately calls the STORE method.  If it is
rvalue, it immediately calls the FETCH method.  However, as far as I
can tell, this optimization requires that Perl know about the Proxy
class in particular.
 
> In particular, I think this would mean making Proxy objects
> automatically call FETCH when returned, unless in reference context.
> 
> In fact, I think I'd rather see the proxy as a closure trait;
> 
>    class MagicVal {
>       has Int $.varies is rw;
> 
>       method varies returns Int is Proxy( :FETCH(&get_varies),
>                                           :STORE(&set_varies) );

But other than that it looks good.  I would name the trait something
other than Proxy probably.  Perhaps `accessor`.

Luke

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About