Re: Method Resolution Order question
Larry, Thanks much, this all makes sense. :) Thanks, Stevan On Jul 14, 2005, at 4:54 PM, Larry Wall wrote: On Thu, Jul 14, 2005 at 04:31:07PM -0400, Stevan Little wrote: : Now, the metamodel currently does not have MMD, and I think "next : METHOD" is not as relevant in SMD. So would it make sense to do: : : next SUPER if $?SELF != $?CLASS; : : or something like that? It comes out to that under single inheritance, but under MI it might well be that the next method that ought to be called is actually a sibling method. This is just to clarify for me (and anyone else paying attention), because this made more sense when I "saw" it. class Foo { method baz { ... } } class Bar { submethod baz { ... } } class FooBar is Foo is Bar {} my $foo_bar = FooBar.new(); $foo_bar.baz() # calls Foo::baz() No need to respond unless I got it wrong :) : Here is some example code which might encounter this: : : class Foo { : method baz { ... } : } : : class Bar is Foo { : submethod baz { ... } : } : : class FooBar is Bar {} : : my $foo_bar = FooBar.new(); : $foo_bar.baz() # calls Foo::baz() : : basically the dispatch goes from Bar::baz, which says "next SUPER" and : the dispatcher then goes to Foo::baz since it is a method. : : Is that correct? It says "next METHOD", which has the same effect under SI. But we don't know whether we're under MI, and we don't know if the dispatcher we're working under has some weird order of visitation, so it's clearer to say "next METHOD" and leave it up to the dispatcher to decide if the SUPER is the next method. It *usually* is, but... : You refer to CREATE and BUILDALL as methods here, but A12 calls them : submethods. Which is correct? The default versions are methods so that they can be inherited. The individual versions defined by classes are submethods unless they intend to be inherited, and force all their subclasses into a new set of default sematics. And they're always called as methods (except when things like .* cheat). : >I believe there's pseudo-code for that in A12. The trick is that you : >can always force a call to a submethod of the "wrong" class by taking : >it as a sub reference and calling it like an ordinary subroutine. : : Okay, this is just as dirty a trick as sneaking up into the metamodel, : so I will leave it that way for now, knowing I need to change it later : :) Of course, the metamodel can do whatever dirty tricks it likes, but in Perl 6 the metamodel might actually implement this particular operation by forcing a sub call through a reference, if the metamodel is implemented in Perl 6. It's the only way we've defined to defeat the .foo dispatcher so far, from a language point of view. (Though simply calling .meta could also be construed as cheating, I guess. Or at least an authorization of cheating on your behalf.) Larry
Re: Method Resolution Order question
On Thu, Jul 14, 2005 at 04:31:07PM -0400, Stevan Little wrote: : > A submethod is simply a method that says "These : >aren't the droids you're looking for" if you call it via either SMD : >or MMD dispatch and the first invocant isn't of the exact run-time : >type of the lexical class. In other words, it just has an implicit : > : >next METHOD if $?SELF != $?CLASS; : > : >at the front. So the dispatch continues until it finds either a : >submethod : >that does have an exact match or a method that isn't a submethod. : : Now, the metamodel currently does not have MMD, and I think "next : METHOD" is not as relevant in SMD. So would it make sense to do: : : next SUPER if $?SELF != $?CLASS; : : or something like that? It comes out to that under single inheritance, but under MI it might well be that the next method that ought to be called is actually a sibling method. : Here is some example code which might encounter this: : : class Foo { : method baz { ... } : } : : class Bar is Foo { : submethod baz { ... } : } : : class FooBar is Bar {} : : my $foo_bar = FooBar.new(); : $foo_bar.baz() # calls Foo::baz() : : basically the dispatch goes from Bar::baz, which says "next SUPER" and : the dispatcher then goes to Foo::baz since it is a method. : : Is that correct? It says "next METHOD", which has the same effect under SI. But we don't know whether we're under MI, and we don't know if the dispatcher we're working under has some weird order of visitation, so it's clearer to say "next METHOD" and leave it up to the dispatcher to decide if the SUPER is the next method. It *usually* is, but... : You refer to CREATE and BUILDALL as methods here, but A12 calls them : submethods. Which is correct? The default versions are methods so that they can be inherited. The individual versions defined by classes are submethods unless they intend to be inherited, and force all their subclasses into a new set of default sematics. And they're always called as methods (except when things like .* cheat). : >I believe there's pseudo-code for that in A12. The trick is that you : >can always force a call to a submethod of the "wrong" class by taking : >it as a sub reference and calling it like an ordinary subroutine. : : Okay, this is just as dirty a trick as sneaking up into the metamodel, : so I will leave it that way for now, knowing I need to change it later : :) Of course, the metamodel can do whatever dirty tricks it likes, but in Perl 6 the metamodel might actually implement this particular operation by forcing a sub call through a reference, if the metamodel is implemented in Perl 6. It's the only way we've defined to defeat the .foo dispatcher so far, from a language point of view. (Though simply calling .meta could also be construed as cheating, I guess. Or at least an authorization of cheating on your behalf.) Larry
Re: Method Resolution Order question
Larry, Thanks for the detailed reply. Just a few more questions and I think I can get this into the metamodel :) On Jul 14, 2005, at 3:40 PM, Larry Wall wrote: On Wed, Jul 13, 2005 at 07:27:52PM -0400, Stevan Little wrote: : The way I am viewing the notion of "current class" for submethods : currently is: : : From inside another method or submethod: : : - a submethod should only be called from the class which defines it. This doesn't sound right to me. There is no distinction between inside or outside. Yes, I am not sure what I was thinking there. Shortly after I wrote this mail I did some work on submethods in the metamodel and realized how silly that idea is :) I also realized that a sepereate submethod dispatch table made no sense either, so scratch that thought out as well. A submethod is simply a method that says "These aren't the droids you're looking for" if you call it via either SMD or MMD dispatch and the first invocant isn't of the exact run-time type of the lexical class. In other words, it just has an implicit next METHOD if $?SELF != $?CLASS; at the front. So the dispatch continues until it finds either a submethod that does have an exact match or a method that isn't a submethod. Now, the metamodel currently does not have MMD, and I think "next METHOD" is not as relevant in SMD. So would it make sense to do: next SUPER if $?SELF != $?CLASS; or something like that? Here is some example code which might encounter this: class Foo { method baz { ... } } class Bar is Foo { submethod baz { ... } } class FooBar is Bar {} my $foo_bar = FooBar.new(); $foo_bar.baz() # calls Foo::baz() basically the dispatch goes from Bar::baz, which says "next SUPER" and the dispatcher then goes to Foo::baz since it is a method. Is that correct? : This means that since Object::bless() calls Object::BUILDALL() it is : all well and good, assuming you have not overridden bless() in your : class, and are calling it $class.bless(). No, Object::bless() (which perhaps delegates to Class.meta.bless so that different meta classes can have different .bless primitives) Okay, this makes sense. calls MyClass.CREATE to create the type, while will be an opaque type if that normal method dispatch runs up the tree to Object::CREATE. (But user classes are allowed to define their own CREATE method to create non-opaque objects.) After the storage is allocated, .meta.bless then calls $newobj.BUILDALL as an ordinary method call on the instance. Again this is overridable by each class, but typically goes back to Object::BUILDALL (which, as usual, probably delegates at least some of the work to the meta class). You refer to CREATE and BUILDALL as methods here, but A12 calls them submethods. Which is correct? : (Object::BUILDALL of course then digs into the metaclass to call : BUILD() for all the superclasses in post-order. I am not sure how to do : that otherwise, submethod or not.) I believe there's pseudo-code for that in A12. The trick is that you can always force a call to a submethod of the "wrong" class by taking it as a sub reference and calling it like an ordinary subroutine. Okay, this is just as dirty a trick as sneaking up into the metamodel, so I will leave it that way for now, knowing I need to change it later :) : However, if you define MyClass::bless, then you will need to define : MyClass::BUILDALL as well. We did not intend that people redefined .bless. It's really intended to be a primitive like .meta. The occasional redefinables are CREATE and BUILDALL, but it's really only intended that BUILD be defined typically. Agreed, .bless should probably never be redefined, I will pull that up into the MetaClass. : > There's some kind of "yes I mean : >you" notion in the dispatcher. It comes out in user-visible terms : >in .*foo calls but not ordinary .foo calls, : : I am not familiar with .*foo calls? Can you elaborate? This is all pretty much straight from A12. I see now, I forgot about those :) : > which call a submethod : >only when the object is actually that type, and otherwise look for an : >ancestral method of that name. : : Yes, to expand upon my above statements. The method resolution would : begin looking in the local submethod table, then move onto the local : method table, and then on up the superclass hierarchy. Is that correct? There is no separate submethod table. From the standpoint of ordinary .foo method resolution they're ordinary methods that happen to say "next METHOD" as a form of failure. Yup, realized that as soon as I tried to implement it :) Thanks, Stevan
Re: Method Resolution Order question
On Wed, Jul 13, 2005 at 07:27:52PM -0400, Stevan Little wrote: : The way I am viewing the notion of "current class" for submethods : currently is: : : From inside another method or submethod: : : - a submethod should only be called from the class which defines it. This doesn't sound right to me. There is no distinction between inside or outside. A submethod is simply a method that says "These aren't the droids you're looking for" if you call it via either SMD or MMD dispatch and the first invocant isn't of the exact run-time type of the lexical class. In other words, it just has an implicit next METHOD if $?SELF != $?CLASS; at the front. So the dispatch continues until it finds either a submethod that does have an exact match or a method that isn't a submethod. : This means that since Object::bless() calls Object::BUILDALL() it is : all well and good, assuming you have not overridden bless() in your : class, and are calling it $class.bless(). No, Object::bless() (which perhaps delegates to Class.meta.bless so that different meta classes can have different .bless primitives) calls MyClass.CREATE to create the type, while will be an opaque type if that normal method dispatch runs up the tree to Object::CREATE. (But user classes are allowed to define their own CREATE method to create non-opaque objects.) After the storage is allocated, .meta.bless then calls $newobj.BUILDALL as an ordinary method call on the instance. Again this is overridable by each class, but typically goes back to Object::BUILDALL (which, as usual, probably delegates at least some of the work to the meta class). : (Object::BUILDALL of course then digs into the metaclass to call : BUILD() for all the superclasses in post-order. I am not sure how to do : that otherwise, submethod or not.) I believe there's pseudo-code for that in A12. The trick is that you can always force a call to a submethod of the "wrong" class by taking it as a sub reference and calling it like an ordinary subroutine. : However, if you define MyClass::bless, then you will need to define : MyClass::BUILDALL as well. We did not intend that people redefined .bless. It's really intended to be a primitive like .meta. The occasional redefinables are CREATE and BUILDALL, but it's really only intended that BUILD be defined typically. : Or is it possible just do $self.Object::BUILDALL()? So can I call a : submethod from a different class if I fully qualify it? No, that would just fail. You have to do the reference casting trick to call it as an ordinary subroutine. We made that hard on purpose. : From outside a method (in "user" space): : : - the invocant of the submethod must be a direct instance of the class : in which the submethod is defined. No inheritance involved. : : Maybe this is too strict, though? What do you think? There is no "user" space distinction. You still just call a method with the ordinary dispatcher, and it still just runs down the list of dispatcher class candidates till it either finds one that's a method or finds one that is a submethod and whose class matches the object's. Of course, that's highly unlikely to match a submethod on anything but the first probe, given the usual visitation order of the standard dispatcher and the fact that virtual method calls always start with the actual run-tiem type of the object, but MMD might have a different idea about order, and the same principle still applies. Plus other dispatchers are possible. The point of a submethod is that it doesn't make sense to call it on anything other than an actual object of this type (where initialization and finalization are examples of where we basically lie about the actual type because we want the various bit of the current object treated as if they were really an ancestral class even though they aren't really). Since that's the point of a submethod, the proper place to put the constraint is on the front of the submethod itself, and let it just fail to be dispatched to if it doesn't want to be dispatched to. In general, unless you are a funny dispatcher like .*foo, you shouldn't be thinking about "how you call them". : > There's some kind of "yes I mean : >you" notion in the dispatcher. It comes out in user-visible terms : >in .*foo calls but not ordinary .foo calls, : : I am not familiar with .*foo calls? Can you elaborate? This is all pretty much straight from A12. : > which call a submethod : >only when the object is actually that type, and otherwise look for an : >ancestral method of that name. : : Yes, to expand upon my above statements. The method resolution would : begin looking in the local submethod table, then move onto the local : method table, and then on up the superclass hierarchy. Is that correct? There is no separate submethod table. From the standpoint of ordinary .foo method resolution they're ordinary methods that happen to say "next METHOD" as a form of failure. The dispatcher doesn't even have to know the
Re: Method Resolution Order question
Larry, On Jul 13, 2005, at 2:30 PM, Larry Wall wrote: : The Syn/Apoc seem to indicate that methods and submethods of the same : name can coexist. So the class definition itself is legal. However, it : brings up an issue when it comes time to call bar(). If the Syn/Apoc is giving that impression, it's giving the wrong impression. Subs, methods, and anything in between all live in the same namespace. The class above is illegal because you're trying to give two things the name &bar in the absence of a "multi". Horray : Can submethods only be called from within the class (like private : methods)? No, they can be called from anywhere. They're just constrained to work only when a dispatcher's idea of "current class" matches the actual class, where "current class" usually means the actual class of the object in question, but can also mean an ancestral class when we're doing BUILDALL, for instance. The way I am viewing the notion of "current class" for submethods currently is: From inside another method or submethod: - a submethod should only be called from the class which defines it. This means that since Object::bless() calls Object::BUILDALL() it is all well and good, assuming you have not overridden bless() in your class, and are calling it $class.bless(). (Object::BUILDALL of course then digs into the metaclass to call BUILD() for all the superclasses in post-order. I am not sure how to do that otherwise, submethod or not.) However, if you define MyClass::bless, then you will need to define MyClass::BUILDALL as well. Or is it possible just do $self.Object::BUILDALL()? So can I call a submethod from a different class if I fully qualify it? From outside a method (in "user" space): - the invocant of the submethod must be a direct instance of the class in which the submethod is defined. No inheritance involved. Maybe this is too strict, though? What do you think? There's some kind of "yes I mean you" notion in the dispatcher. It comes out in user-visible terms in .*foo calls but not ordinary .foo calls, I am not familiar with .*foo calls? Can you elaborate? which call a submethod only when the object is actually that type, and otherwise look for an ancestral method of that name. Yes, to expand upon my above statements. The method resolution would begin looking in the local submethod table, then move onto the local method table, and then on up the superclass hierarchy. Is that correct? Thanks, Stevan
Re: Method Resolution Order question
On Wed, Jul 13, 2005 at 12:51:49PM -0400, Stevan Little wrote: : Hello, : : More questions for the metamodel. I am trying to add proper submethod : and private method handling and I have a question about method : resolution order as a whole. I asked a similar question last week, but : this time I have more details :) : : Given this class: : : class Foo { : submethod bar { ... } : method bar { ... } : } : : and given this code: : : Foo.new().bar() : : What should happen? : : The Syn/Apoc seem to indicate that methods and submethods of the same : name can coexist. So the class definition itself is legal. However, it : brings up an issue when it comes time to call bar(). If the Syn/Apoc is giving that impression, it's giving the wrong impression. Subs, methods, and anything in between all live in the same namespace. The class above is illegal because you're trying to give two things the name &bar in the absence of a "multi". : Should submethod bar() be called first, then method bar() after it? : Should method bar() be called first, then submethod bar() after it? Question doesn't arise. : Can submethods only be called from within the class (like private : methods)? No, they can be called from anywhere. They're just constrained to work only when a dispatcher's idea of "current class" matches the actual class, where "current class" usually means the actual class of the object in question, but can also mean an ancestral class when we're doing BUILDALL, for instance. There's some kind of "yes I mean you" notion in the dispatcher. It comes out in user-visible terms in .*foo calls but not ordinary .foo calls, which call a submethod only when the object is actually that type, and otherwise look for an ancestral method of that name. : And if submethods can only be called from within the class, then how do : I handle this: : : class Foo { : submethod bar { ... } : method bar { ... } : method baz { : $?SELF.bar() : } : } : : Foo.new().baz() Again, illegal class. : Thanks, : : Stevan :
Method Resolution Order question
Hello, More questions for the metamodel. I am trying to add proper submethod and private method handling and I have a question about method resolution order as a whole. I asked a similar question last week, but this time I have more details :) Given this class: class Foo { submethod bar { ... } method bar { ... } } and given this code: Foo.new().bar() What should happen? The Syn/Apoc seem to indicate that methods and submethods of the same name can coexist. So the class definition itself is legal. However, it brings up an issue when it comes time to call bar(). Should submethod bar() be called first, then method bar() after it? Should method bar() be called first, then submethod bar() after it? Can submethods only be called from within the class (like private methods)? And if submethods can only be called from within the class, then how do I handle this: class Foo { submethod bar { ... } method bar { ... } method baz { $?SELF.bar() } } Foo.new().baz() Thanks, Stevan