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

2005-06-26 Thread Sam Vilain

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)

2005-06-26 Thread BÁRTHÁZI András

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)

2005-06-26 Thread Piers Cawley
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)

2005-06-26 Thread BÁRTHÁZI András

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)

2005-06-26 Thread Juerd
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)

2005-06-26 Thread BÁRTHÁZI András

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)

2005-06-26 Thread Juerd
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( ... );

2005-06-26 Thread Sam Vilain

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(%hashkey);

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 $_

2005-06-26 Thread Sam Vilain

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( ... );

2005-06-26 Thread Luke Palmer
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