Larry,
On Oct 25, 2005, at 4:37 PM, Larry Wall wrote:
On Mon, Oct 24, 2005 at 06:33:20AM -0700, Ashley Winters wrote:
: # behavior through prototype -- guessing realistic syntax
: Base.meta.add_method(
: do_it => method ($arg) {
: say "doing $arg!";
: });
:
:
: # or, just add it to a single instance
: $x.meta.add_method(
: do_it => method ($arg) {
: say "doing $arg!";
: });
I don't have a comment on your actual question, but I'd like to use
this opportunity to point out the symmetry of Base and $x at this
point, and the fact that .meta can't simply call .add_method in the
metaclass, or it would lose track of the original invocant, which is
needed to convey both class and instance information. I'm not sure
it's even possible to say
$m = $x.meta;
$m.addmethod($arg);
The only way that can work is if $x.meta returns a shadow class that
is prebound only to $x. (Though that might explain how .addmethod
knows it's only adding a method to the object.)
This is actually the principe behind the Ruby style singleton methods
(the shadow class), it basically creates an anon-class which inherits
from $x's original class, then it rebinds/blesses $x into the anon-
class. It is very simple really :)
As for if this is/should be accessible through .meta, i am not sure
that is a good idea. The reason being is that .meta brings with it
the idea of metaclasses, which then relates to classes, and so now
the user is thinking they are accessing the metaclass of the class of
which $x is an instance.
I would suggest instead that we have a method, which is found in
Object which allows instances to add methods to themselves (and only
themselves). In Ruby this is called 'add_singleton_method' or
something like that. I use that same name in the metamodel prototype
too.
In the absence of that, what's going on seems more like
$x.META::addmethod($arg);
where META:: is smart enough to dispatch to the proper metaclass
without
throwing away the invocant, and then the metaclass decides what to do
based on the instancehood of $x.
I am not sure I like this for 2 reasons.
1) META:: smells like ::SUPER, and that feels like re-dispatching to
me, which is not really what we need to be doing.
2) there is not need to send this back to the metaclass level. The
whole thing could be accomplished as an instance method of Object.
Here is how it could be done.
class ShadowClass does Class {}
class Object is reopened {
method add_singleton_method (Str $label, Method $method) {
if ($?SELF.class.class != ShadowClass) {
my $shadow = ShadowClass.new();
$shadow.meta.superclasses([ $shadow ]);
$?SELF.class = $shadow;
}
$?SELF.class.meta.add_method($label, $method);
}
}
Stevan