S12 Patch for metacalls, Representation API (Was: Re: Foo.HOW.metamethod vs Foo.^metamethod)

2008-06-11 Thread Daniel Ruoso
Seg, 2008-06-09 às 17:51 -0700, Larry Wall escreveu:
 On Sat, Jun 07, 2008 at 09:49:03PM +0100, Daniel Ruoso wrote:
 : 2) Assume the capture-translation and define that
 : $foo.HOW.can($foo,'bar') keeps the $how as the invocant and must receive
 : the referring object as first argument.
 I prefer this approach, I think.

I took the liberty to write a patch to S12 with this new context. The
extended format $foo.HOW.methods($foo) becomes a little awkward,
specially for Class based OO. Maybe there should be a more extended
modification to promote the .^methods syntax, since $foo.HOW is then
more usefull for prototype-based OO, where $foo.HOW might be, for
instance, Prototype::Delegation::C3 or Prototype::Concatenation.

This actually brings me to another issue, which is how much do we expect
for this prototype-based meta implementations to be exchangeable between
Perl 6 implementations?

The point is that they *must* be representation independent, so that you
can use it with whatever low-level object metainstance (in the Moose
jargon) you like, and for that to be possible, we need a representation
API. SMOP is already pointing in that direction, take a look at:

  * http://www.perlfoundation.org/perl6/index.cgi?smop_oo_api
  * http://svn.pugscode.org/pugs/v6/smop/src-s1p/P6Meta.pm

daniel

__DATA__

Index: S12.pod
===
--- S12.pod (revision 14546)
+++ S12.pod (working copy)
@@ -123,11 +123,15 @@
 CHOW method.  A class object is just considered an empty
 instance in Perl 6, more properly called a prototype object, or just
 protoobject.
-The actual class object is the metaclass object pointed to by the
-CHOW syntax.  So when you say CDog, you're referring to both a
-package and a protoobject, that latter of which points to the
-actual object representing the class via CHOW.  The protoobject
-differs from an instance object not by having a different
+
+In a class-based OO implementation, the actual class object is the
+metaclass object pointed to by the CHOW syntax.  So when you say
+CDog, you're referring to both a package and a protoobject, that
+latter of which points to the actual object representing the class via
+CHOW. In a prototype-based OO implementation, on the other hand, the
+metaclass object is probably going to be shared by several types and
+the methods are most likely going to be stored in the prototypes.  The
+protoobject differs from an instance object not by having a different
 type but rather in the extent to which it is defined.  Some objects
 may tell you that they are defined, while others may tell you that
 they are undefined.  That's up to the object, and depends on how the
@@ -1892,23 +1896,29 @@
 $x === $y
 $obj.bless(%args)
 
-Every class has a CHOW function/method that lets you get at the
-class's metaobject, which lets you get at all the metadata properties
-for the class (or other metaobject protocol) implementing the objects
-of the class:
+Every object, defined or not, has a CHOW function/method that lets
+you get at the metaobject, which lets you get at all the metadata
+properties for the type (or other metaobject protocol) implementing
+the objects of the type:
 
-MyClass.methods()   # call MyClass's .methods method (error?)
-MyClass.HOW.methods()   # get the method list of MyClass
+MyClass.methods()# call MyClass's .methods method (error?)
+MyClass.HOW.methods(MyClass) # get the method list of MyClass
 
 The C^ metasyntax is equivalent to C.HOW:
 
-MyClass.HOW.methods()   # get the method list of MyClass
-^MyClass.methods()  # get the method list of MyClass
-MyClass.^methods()  # get the method list of MyClass
+MyClass.HOW.methods(MyClass) # get the method list of MyClass
+^MyClass.methods(MyClass)
 
-Each object of the class also has a C.HOW or C.^ method:
+When using the C^ metasyntax in the method invocation, it also
+implies a translation in the capture, passing the invocant as first
+argument:
 
-$obj.HOW.methods();
+MyClass.HOW.methods(MyClass) # get the method list of MyClass
+MyClass.^methods()   # equivalent shorter syntax
+
+Each object of the type also has a C.HOW or C.^ method:
+
+$obj.HOW.methods($obj);
 $obj.^methods();
 
 Class traits may include:
@@ -1964,9 +1974,9 @@
 Strictly speaking, metamethods like C.isa(), C.does(), and C.can()
 should be called through the meta object:
 
-$obj.HOW.can(bark)
-$obj.HOW.does(Dog)
-$obj.HOW.isa(Mammal)
+$obj.HOW.can($obj, bark)
+$obj.HOW.does($obj, Dog)
+$obj.HOW.isa($obj, Mammal)
 
 or
 
@@ -1992,7 +2002,7 @@
 
 actually calls:
 
-$obj.HOW.does(Dog)
+$obj.HOW.does($obj, Dog)
 
 which is true if C$obj either does or isa CDog (or isa
 something that does CDog).  If CDog is a subset, any additional




Re: Foo.HOW.metamethod vs Foo.^metamethod

2008-06-09 Thread Larry Wall
On Sat, Jun 07, 2008 at 09:49:03PM +0100, Daniel Ruoso wrote:
: 2) Assume the capture-translation and define that
: $foo.HOW.can($foo,'bar') keeps the $how as the invocant and must receive
: the referring object as first argument.

I prefer this approach, I think.

Larry


Foo.HOW.metamethod vs Foo.^metamethod

2008-06-08 Thread Daniel Ruoso
Hi,

When implementing prototype OO, the HOW for objects with different
behaviours will be shared. This issue is not new, but before we thought
that it would be possible to solve that by forcing $foo.HOW to be a
proxy object that would rewrite the call putting $foo as the invocant.

Me and nothingmuch, during PPW in Braga, got more into that issue, and
we came to the realisation that this is not really possible, as it might
be actually desirable to have a real meta object, storing
meta-information that would be part of that metaobject implementation.

The HOW might be implementing some kind of RPC, for instance, and that
way, it might need to store some meta-meta-information, like the address
of the RPC endpoint. This makes the idea of the proxy object inviable
because the user might need to talk to the HOW as a real object.

That way, 

$foo.^can('bar') cannot be the same as $foo.HOW.can('bar'), because the
first has both $foo and $foo.HOW implied, while, in the last, $foo
cannot be taken from anywhere.

Therefore I suggest making $foo.^method format the only way to get
metamethods related to this object, while $foo.HOW would have a
behaviour which would be implementation dependent (at least until it's
standartized)

SMOP will have $foo.^can('bar') actually translated to
$foo.HOW.can($foo, 'bar'), which will keep $foo.HOW as the invocant, and
prepend the referring object as the first positional argument (following
the example of the sub-dispatch fallback).

In that case, we might either:

1) remove all references of $foo.HOW.can('bar') and say that this is
implementation specific (since Class-based OO can implement it that way)

2) Assume the capture-translation and define that
$foo.HOW.can($foo,'bar') keeps the $how as the invocant and must receive
the referring object as first argument.

daniel