Magic mutators and my $var is Proxy( ... );
To me it is a trivial case that you want to provide a fake attribute which for all intents and purposes behaves exactly like there was a real attribute there, backing against another attribute. A Date object is a classic example of this; you want to provide 0-based and 1-based attributes, which you want to present as equivalent to each other. 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? 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? Such as; my $foo = MagicVal.new(); $foo.varies = 5;# sets to 6; say $foo.varies;# says 8 say $foo.varies;# says 10 my $var = $foo.varies; # $var is proxy for attribute say $foo.varies;# says 12 say $var; # says 14 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. 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. 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) ); method get_varies { $.varies += 2 }; method set_varies { $.varies = $^v + 1 }; } Of course this wouldn't preclude the possibility of using the syntax in A06 where it is more suited to the problem at hand. Also, in the case where you do take a reference of a $foo.varies, then a Proxy object could be constructed to DTRT based on the information there. This would make the "is Proxy()" construct effectively a compile-time want() switch. Any opinions on this? Sam.
OO magic (at least for me)
Hi, I'm wondering, if it's possible with Perl 6 or not? class MyClass { method mymethod($par) { say "mymethod called!"; } } class ExClass is MyClass { mymethod(12); } #> pugs myprog mymethod called! I would like to use mymethod to add ExClass some methods, etc. /// Just another problem, related to the above: class MyClass { method whenmother() { say "MyClass is parent now!!!"; say "Her child name is: " ~ ; } } class Child is MyClass { } #> pugs myprog MyClass is parent now!!! Her child name is: Child Bye, Andras
Re: OO magic (at least for me)
BÁRTHÁZI András <[EMAIL PROTECTED]> writes: > Hi, > > I'm wondering, if it's possible with Perl 6 or not? > > class MyClass { > > method mymethod($par) { > say "mymethod called!"; > } > > } > > class ExClass is MyClass { > > mymethod(12); > > } > > #> pugs myprog > mymethod called! > > I would like to use mymethod to add ExClass some methods, etc. > > /// > > Just another problem, related to the above: > > class MyClass { > > method whenmother() { > say "MyClass is parent now!!!"; > say "Her child name is: " ~ ; > } > > } > > class Child is MyClass { > } > > #> pugs myprog > MyClass is parent now!!! > Her child name is: Child I'd like to hope so. Actually, I don't think that this *specific* functionality should be in the core, but the ability to implement it (just needs a unified notifcation scheme that gets tickled when new classes, methods, subs, packages, etc, get added to the image -- more detailed behaviour is a SMOP).
Re: OO magic (at least for me)
Hi! I'm trying to answering my questions. Still interested in some official answer. :) --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- class MyMethod { method fun1() { fun2(); } method fun2() { say "fun2!"; } } class Child is MyMethod { } Child.fun1(); --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- *** No compatible subroutine found: "&fun2" I'm wondering why, but maybe, it's OK. --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- class MyMethod { method fun1() { fun2(); } sub fun2() { say "fun2!"; } } class Child is MyMethod { } Child.fun1(); --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- fun2! Sounds good. It seems to me, that I can call fun2() from inside MyMethod, from everywhere. OK, Child is MyMethod, so can I do it there too? No. :( --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- class MyMethod { method fun1() { fun2(); } sub fun2() { say "fun2!"; } } class Child is MyMethod { fun2(); } Child.fun1(); --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- *** No compatible subroutine found: "&fun2" The problem is calling fun2() from Child's declaration. As I think, the calling just happens at when interpreting the declaration of Child, but the scope is not Child's scope. Why? Let's try Child.fun2()! --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- class MyMethod { method fun1() { fun2(); } sub fun2() { say "fun2!"; } } class Child is MyMethod { Child.fun2(); } Child.fun1(); --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- 8< --- fun2! Works well. Is it a not yet implemented feature in Pugs, or is by design? Still don't know, how can a method/sub automagically called, when I inherite a class. I would like to use the syntax you can see in my example #1, but the syntax of example #2 is still OK. I would like to use calling the classes own methods/subs when declaring a child, and calling a method/sub automatically, when I'm declaring a child. Bye, Andras
Re: OO magic (at least for me)
BÁRTHÁZI András skribis 2005-06-26 19:35 (+0200): > method fun1() { fun2(); } > method fun2() { say "fun2!"; } > *** No compatible subroutine found: "&fun2" fun2 is a method, not a sub. You need method syntax to call it: ./fun2; > class MyMethod { method fun1() { fun2(); } sub fun2() { say "fun2!"; } > } class Child is MyMethod { } > Child.fun1(); > Sounds good. It seems to me, that I can call fun2() from inside > MyMethod, from everywhere. OK, Child is MyMethod, so can I do it there > too? No. :( IIRC, that's what submethods are for. Submethods aren't inherited. It is unclear to me whether subs are. Two requests: 1. Please indent code and don't use cutting lines. 2. Please use visually more different names, fun1 and fun2 look a lot alike. Consider foo and bar. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: OO magic (at least for me)
Hi, method fun1() { fun2(); } method fun2() { say "fun2!"; } *** No compatible subroutine found: "&fun2" fun2 is a method, not a sub. You need method syntax to call it: ./fun2; Hmm. It really works. :) I'm getting the idea, what's the difference between methods and subs. Anyway, my implementation is, that ./ means self's method - and the class is not an instance, so it has no self. ./fun2 still not working at the second class's declaration. IIRC, that's what submethods are for. Submethods aren't inherited. It is unclear to me whether subs are. Do you mean, that submethods for class methods (I don't know, if is it the official name of the non instance methods)? I don't think so. Bye, Andras
Re: OO magic (at least for me)
BÁRTHÁZI András skribis 2005-06-26 20:07 (+0200): > Hmm. It really works. :) I'm getting the idea, what's the difference > between methods and subs. Anyway, my implementation is, that ./ means > self's method - and the class is not an instance, so it has no self. The invocant can be a class too. > Do you mean, that submethods for class methods (I don't know, if is it > the official name of the non instance methods)? I don't think so. No. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Magic mutators and my $var is Proxy( ... );
Sam Vilain wrote: To me it is a trivial case that you want to provide a fake attribute which for all intents and purposes behaves exactly like there was a real attribute there, backing against another attribute. A Date object is a classic example of this; you want to provide 0-based and 1-based attributes, which you want to present as equivalent to each other. FWIW, I think this question also applies to fetching members from a hash collection. For example, if you have a function; sub foo($foo) { $foo || "bar" } And you call it, passing it a hash slot; foo(%hash); Then it will be auto-vivified, as in Perl 5; because a reference to the slot had to be taken. Actually there is no reference taken; it's a read-only binding of the hash slot. But either way, it is a read-only point in the signature that is affecting the input argument, which is arguably (right^wrong). By returning a Proxy object 'tied' to the slot, then this autovivification could be circumvented and the straightforward implementation - passing bound variables as transparent references, continues to be acceptable. Albeit requiring that the Hash::postcircumfix:<{ }> method is a Proxy method, too. Sam.
Re: AUTLOAD and $_
Piers Cawley wrote: For myself, I'd like to see AUTOLOAD with a signature along the lines of: sub AUTOLOAD (Symbol $sym, ArgumentCollection $args, Continuation $cc) returns (Code | Pair) { ... } This presupposes a deal of support infrastructure, but also provides flexibility. For the 'NullObject' case, you'd simply do C<$cc()> to return directly to the caller, skipping over whatever Perl is up to. That's an excellent suggestion. After your very enlightening discussion about continuations in IRC, this popped to mind as an interesting application for them, along with exception handlers. This would be great for at least AUTOSUB and AUTOMETH. However, for AUTOLOAD we're looking for simple Perl 5 alikeness. And in Perl 5, the sub name was passed out of band. So, we need a compromise somewhere, please @cabal.pick: - just go for old AUTOLOAD + $AUTOLOAD interface and spit warnings profusely -OR- { - allow topic to refer to variables in lexical scope, but not in @_ (and pick a good name for $?SUB.called_as) -OR- - allow generic out-of-band parameters to be passed in } implies { - there needs to be a special subroutine calling method, similar to .assuming that lets you do this -OR- - the method prototype, and specify some way that methods defined without a signature can inherit it from somewhere else. } -OR- - declare the topic to be the only out-of-band parameter that does this. To avoid it being an accidental global, it would need to be declared with "my $_" when used in this manner (of course, other methods like for, given, etc that set it have the declaration implicit). -OR- - scrap complete AUTOLOAD interface compatibility -OR- - insert solution here ;) Sam.
Re: Magic mutators and my $var is Proxy( ... );
On 6/26/05, Sam Vilain <[EMAIL PROTECTED]> 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