Submethods

2 views
Skip to first unread message

Stevan Little

unread,
Jul 5, 2005, 10:13:52 PM7/5/05
to perl6-l...@perl.org
Again with the metamodel stuff :P

So, I am trying to implement the submethods correctly, and some
questions occurred to me.

The concept of non-inherited infrastructural methods is fairly simple
to accomplish in the meta-model, by just giving submethods their own
dispatch table inside the metaclass. However where I am somewhat
confused is in how and when they get called.

Take this example for instance:

class Foo {
method bar () { ... }
submethod bar () { ... }
}

Is this an error (Synopsis 12 seems to indicate it is *not* an error)?

When I call bar() on an instance of Foo, which is called? The method?
or the submethod? Is it somehow dependent upon the calling context?
(called from within the class, or from outside the class). Take for
instance, this example:

class Foo {
method bar () { ... }
submethod bar () { ... }

method baz ($self:) {
$self.bar() # which one does this call?
}
}

Or are both called? if so, in what order? On method resolution, should
I first check the submethod table? or the method table (and on up the
superclass chain)?

Thanks,

Stevan

Stevan Little

unread,
Jul 6, 2005, 9:10:36 AM7/6/05
to "TSa (Thomas Sandlaß)", perl6-l...@perl.org
Thomas,

On Jul 6, 2005, at 7:14 AM, TSa (Thomas Sandlaß) wrote:
> One entry for &bar:(Foo) and one for &bar:(MetaClass[Foo])?

You seem to indicate that submethods are not to be used on instances,
and instead to be used on the underlying metaclass. I did not see
anything of the sort in (Syn|Apoc)12 or in my (limited) search of the
mailing list. Can you point me to that information?

Thanks,

Stevan

Stevan Little

unread,
Jul 6, 2005, 11:28:47 AM7/6/05
to "TSa (Thomas Sandlaß)", perl6-l...@perl.org
Thomas,

On Jul 6, 2005, at 10:19 AM, TSa (Thomas Sandlaß) wrote:
> S12 says in the section Submethods: "A submethod is called only when a
> method call is dispatched directly to the current class."
>
> And without finding a reference I think it was said that "the invocant
> of a submethod is a class object".

I took that statement to mean that methods were not inherited, and that
they can only be called from methods within the class they were
defined.

> From this I have derived what I said. Nonetheless there seems to be
> some overlap in particular in the construction process which is
> characterized as involving an unitialized object. So in that case
> some macro magic might make the instance available to the submethod.
> But this will be a non-invocant parameter.

This is a possibility, however, i think that submethods are more
valuable if they dealt with invocants rather than just with classes
(metaclasses).

It seemed to me from A12 that submethods are meant to define an
interface of some kind, the BUILD/DESTROY submethods being the perfect
example. However this means that BUILDALL and DESTROYALL need to be
fairly magical. I say this because BUILDALL would have to extract some
kind of class list from it's invocant, and call
$self.SomeClass::BUILD() on each class. And since BUILDALL is
(supposedly) defined in Object, (and I assume it too is a submethod),
it becomes critical (in some cases) for Object::new to be called.

=begin RANT/SUGGESTION

While I like the idea of infastructural methods, I think maybe we
should place more restrictions on them. Ideally the object model itself
would create a set of these "interfaces". One for creation
(BUILD/BUILDALL) and for destruction (DESTROY/DESTROYALL), and maybe a
few others. And then the model itself would utilize them, but the user
would not (easily) be able to add to these submethods.

I think this would greatly simplify the concept of submethods, and also
allow for more advanced users to add new "interfaces" to the object
model. This could (theoretically) allow for low-level manipulation of
the object model while still making it simple for not-as-advanced users
to use it easily by just following the interface.

For instance, here is a very simply and naive example of a persistant
interface of sorts:

Object.meta.add_submethod('FREEZE' => sub { ... });
Object.meta.add_submethod('THAW' => sub { ... });

Object.meta.add_submethod('FREEZEALL' => sub ($self:) {
for $class -> $self.meta.get_class_list() {
$self.($class)::FREEZE();
}
});

etc etc etc ...

Then a user could simply define a FREEZE and THAW submethod in each of
their classes they want to be persistent.

Or something like that :)

=end RANT/SUGGESTION

Anyway, just a thought.

Stevan


>
> But mind the sig!
> --
> $TSa =:= all( none( @Larry ), one( @p6l ))
>

Larry Wall

unread,
Jul 6, 2005, 1:45:25 PM7/6/05
to perl6-l...@perl.org
On Wed, Jul 06, 2005 at 11:28:47AM -0400, Stevan Little wrote:
: It seemed to me from A12 that submethods are meant to define an
: interface of some kind, the BUILD/DESTROY submethods being the perfect
: example. However this means that BUILDALL and DESTROYALL need to be
: fairly magical. I say this because BUILDALL would have to extract some
: kind of class list from it's invocant, and call
: $self.SomeClass::BUILD() on each class. And since BUILDALL is
: (supposedly) defined in Object, (and I assume it too is a submethod),
: it becomes critical (in some cases) for Object::new to be called.

Most of these submethods will have a generic ordinary method backing
them up in Object. But Object::new isn't where that magical call to
BUILDALL happens. It's the SomeClass.bless that does it magically,
and the default Object::new just happens to call .bless.

: =begin RANT/SUGGESTION


:
: While I like the idea of infastructural methods, I think maybe we
: should place more restrictions on them. Ideally the object model itself
: would create a set of these "interfaces". One for creation
: (BUILD/BUILDALL) and for destruction (DESTROY/DESTROYALL), and maybe a
: few others. And then the model itself would utilize them, but the user
: would not (easily) be able to add to these submethods.

But we want people to be able to add BUILD methods easily.

: I think this would greatly simplify the concept of submethods, and also

: allow for more advanced users to add new "interfaces" to the object
: model. This could (theoretically) allow for low-level manipulation of
: the object model while still making it simple for not-as-advanced users
: to use it easily by just following the interface.

Well, bear in mind that declarators like "submethod" are just disguised
calls on some metaobject already.

: For instance, here is a very simply and naive example of a persistant

: interface of sorts:
:
: Object.meta.add_submethod('FREEZE' => sub { ... });
: Object.meta.add_submethod('THAW' => sub { ... });
:
: Object.meta.add_submethod('FREEZEALL' => sub ($self:) {
: for $class -> $self.meta.get_class_list() {
: $self.($class)::FREEZE();
: }
: });
:
: etc etc etc ...

Well, sure, except you might want the methods in Object to be
inherited, and use submethods only for specific overrides of the
default. But the syntax seems a bit klunky. I suspect it's just
something more like "Object does FreezeThawDefault".

: Then a user could simply define a FREEZE and THAW submethod in each of

: their classes they want to be persistent.
:
: Or something like that :)

I don't think that's terribly far away from what we've got already.

Larry

Larry Wall

unread,
Jul 6, 2005, 12:43:24 PM7/6/05
to perl6-l...@perl.org
On Wed, Jul 06, 2005 at 04:19:40PM +0200, "TSa (Thomas Sandlaß)" wrote:
: Stevan Little wrote:
: >You seem to indicate that submethods are not to be used on instances,
: >and instead to be used on the underlying metaclass. I did not see
: >anything of the sort in (Syn|Apoc)12 or in my (limited) search of the
: >mailing list. Can you point me to that information?
:
: S12 says in the section Submethods: "A submethod is called only when a
: method call is dispatched directly to the current class."

Ah, you're reading a little too much into an imprecise statement.
The intent is not to limit it to class methods--it's using "current
class" to be inclusive of its members. It should say something more
like

A submethod is called only when a dispatcher decides to call
a method via this exact class. This can be because

a) this class, out of all the candidates, happens to be the
class the dispatcher is currently thinking about, or

b) the method call itself is qualified to specify which class
to call explicitly (and for that particular class only, the
constraint on exact class matching is relaxed as if it were
an ordinary subroutine call). Or

c) you call a submethod as an MMD function, in which case the
first invocant of a submethod is constrained to be an exact
class match, or resolve to an ordinary method. Or

d) you call it as a qualified function name, in which case it's
a simple function call.

: And without finding a reference I think it was said that "the invocant


: of a submethod is a class object".

You won't find that one because I don't think anyone ever said it.

: From this I have derived what I said. Nonetheless there seems to be


: some overlap in particular in the construction process which is
: characterized as involving an unitialized object. So in that case
: some macro magic might make the instance available to the submethod.
: But this will be a non-invocant parameter.

Nope, it's just the normal invocant. Submethods differ from ordinary
methods only in not being derivable. (Well, and the fact that they
often operate on partially instantiated objects, as you point out.)

Now in the particular case of a CREATE submethod, you have to get the
class because object isn't created yet. But generally you don't
need to define one of those unless you don't want to use the built-in
opaque type. So the usual course of events is that some constructor
(probably called "new") calls MyClass.bless(%args) and that in turn
calls

my $newobj = MyClass.CREATE(%args);
$newobj.BUILDALL(%args)

which, after calling all the ancestral BUILDs, calls

$newobj.MyClass::BUILD(%args)

or maybe

$newobj.=MyClass::BUILD(%args)

or possibly even

MyClass::BUILD($newobj, %args)

if it doesn't want to fail over to Object::BUILD in the absence of
MyClass::BUILD.

But all that's behind the scenes. The basic cargo cult version
for naive users is, "Write a 'BUILD' submethod if you want to
initialize the attributes with dynamic data that can't be expressed
with default values. And write your own constructor if you don't like
the built-in default constructor. Just make sure your own constructor
calls $class.bless(%args)."

Larry

Stevan Little

unread,
Jul 6, 2005, 3:19:57 PM7/6/05
to Larry Wall, perl6-l...@perl.org
Larry,

Okay, I reviewed A12, and I think I have now managed to implement the
proper object creation behavior in the meta model.

Currently it is somewhat limited, but this is the order of events (as I
understand it from A12).

- First Object.new calls Object.bless passing all named arguments.

- Object.bless then calls Object.CREATE which then returns a data
structure for the instance (P6opaque only right now).

- Object.bless then "blesses" this structure (since the prototype is in
Perl5 it just passes the structure returned by CREATE into
CORE::bless(), I am sure it will be different in the proper Perl6).

- Object.bless then calls $instance.BUILDALL (again passing all the
named params).

- $instance.BUILDALL then does a post-order traversal of the class
hierarchy calling BUILD on all classes (again passing in the named
parameters).

Of course CREATE, BUILDALL and BUILD are not proper submethods yet
because Perl6::Object is not self defining yet. And it only supports
'P6opaque' right now, but I think I have the ordering of events
correct, however, please correct me if I am wrong.

Oh yeah, and all that silliness I wrote below,.. ignore it :)

Thanks,

Stevan

Reply all
Reply to author
Forward
0 new messages