Re: Why submethods
HaloO, Luke Palmer wrote: On 10/29/05, Damian Conway [EMAIL PROTECTED] wrote: So we need a mechanism that is externally (i.e. from a class interface point-of-view) a subroutine, but internally has the features of a method (i.e. has an invocant). Since it's externally sub-like but internally method-like, we call this useful construct a submethod. Wouldn't the semantics fall out naturally from 1) beeing a scoped 'our sub' 2) the topic type ^_ of the topic item $_ beeing contra-variantly defined to the concrete class type? Number 1) assumes that a sub definition in a class without my or our gets a sig of :(Any $_ = CALLER$_, [EMAIL PROTECTED]). The property 2) ensures the non-inheritance indirectly because an overriding sub in a derived class would permit the Foo::bar application. That is Luke's example could read class Foo { has $.data; # creates rw accessor our sub bar # sig is :( void: Foo $_, [EMAIL PROTECTED] ) { $.data = 23; # Not allowed outside of class scope? # .data = 23; # Or force through accessor? } } my $foo = Foo.new; $foo.bar; # binds $_ := $foo and all member refs through $foo, # then calls Foo::bar with empty @_ say $foo.data; # prints 23 For most of that, doesn't a private method suffice? When it doesn't, I feel uneasy about: class Foo { submethod bar() { ... } } my $foo = Foo.new; $foo.bar; If that's externally sub-like, why does it look so much like a method? Isn't looking like a method more a feature of the dot syntax than anything else? Does bar($foo) cause the same perception? If my signature assumptions above are correct then an argumentless bar call without invocant is a too few arguments error. If I understand the term 'package dispatch' of Sam Vilain correctly the package that contains class Foo would maintain a dispatch into class scoped subs depending on the immediate class---is that the eigenclass?---of the invocant. That is we could define class Bar { has $.data; # creates rw accessor our sub bar # sig is :( void: Bar $_, [EMAIL PROTECTED] ) { $.data = 42; } } in addition to the Foo from above and then sub package_dispatched ($x) { $x.bar } my $bar = Bar.new; package_dispatched( $foo ); say $foo.data; # 23 package_dispatched( $bar ); say $bar.data; # 42 But I can understand that Damian thinks that spelling 'our sub' as 'submethod' is good documentation and not a subtlety. OTOH, a 'my sub' is not considered too subtle. Actually a 'has sub foo ...' form might be an alternate spelling for 'has .foo = sub ...' and we can drop the strange word 'submethod' and nicely unify all code types. That is sub = package dispatch on void method = unary dispatch on single invocant item type multi = symmetric multi dispatch on invocant tuple type or left biased successive single dispatch on invocant list or a mix of both --
Re: Why submethods
DC == Damian Conway [EMAIL PROTECTED] writes: DC But factoring method implementations out into a subroutines is DC also extremely annoying, because a subroutine doesn't provide the DC internal conveniences that a method does. In particular, it DC doesn't have an invocant and so you can't call $.attrs or DC .methods. Instead you would have to pass the invocant to the DC subroutine call as an argument and then call accessors and methods DC explicitly through that argument. DC So we need a mechanism that is externally (i.e. from a class DC interface point-of-view) a subroutine, but internally has the DC features of a method (i.e. has an invocant). Since it's externally DC sub-like but internally method-like, we call this useful construct DC a submethod. so it sounds like to me these are methods private to this class. they can't found by any other class (via inheritance). so what is the external sub interface for? we can see the need for private worker methods and even p5 has a convention of marking such subs with a leading _. uri -- Uri Guttman -- [EMAIL PROTECTED] http://www.stemsystems.com --Perl Consulting, Stem Development, Systems Architecture, Design and Coding- Search or Offer Perl Jobs http://jobs.perl.org
Re: Why submethods
On Sat, 2005-10-29 at 17:30 -0400, Stevan Little wrote: However, it could also be that the creator of Foo did not intend for subclasses to be able to Just Work, and that the whole idea of Foo is to do a Template Method style pattern in which subclasses must implement the help_process_data submethod in order for things to work. This is an entirely valid usage for a submethod, and in fact, I think it is an excellent way for implementing the Template Method pattern. Hmm. I think I much prefer; method you_must_implement { ... } or a trait, perhaps method you_must_implement is required; I think that methods disappearing out of scope in subclasses is just Nasty And Wrong™, for the exact reason Luke outlined. Side-effects like that are just asking for trouble IMHO. It is also possible that we could bring over the role idea of required methods and have the same basic principle relate to classes and submethods. If marked as such, a submethod is required to be implemented by a subclass, or class composition fails. I think that could be a useful feature which would allow very safe re-use along those lines. Good point, which is why the is required as above would be better. It seems to me that there's an awful lot of specification going into these varied types of methods. Method Type Purpose DispatchVisibility ---|--|---| $.method()| external API| MMD | all $.submethod() | refactoring | package | single $:private() | internal API| package | single I must admit I also fail to see the difference between submethods and private methods. And what do I use for methods that I don't want to make visible to the world? Perhaps a more useful definition might be that submethods are only available on $?SELF (and are still subject to normal dispatch). Sam.
Re: Why submethods
On 10/29/05, Damian Conway [EMAIL PROTECTED] wrote: So we need a mechanism that is externally (i.e. from a class interface point-of-view) a subroutine, but internally has the features of a method (i.e. has an invocant). Since it's externally sub-like but internally method-like, we call this useful construct a submethod. Hmm, thanks. For most of that, doesn't a private method suffice? When it doesn't, I feel uneasy about: class Foo { submethod bar() { ... } } my $foo = Foo.new; $foo.bar; If that's externally sub-like, why does it look so much like a method? Another thing that scares me with the utility sub point of view follows: class Foo { method process_data($data) { $.help_process_data($data); } submethod help_process_data($data) { $data+1; } } Foo.new.process_data(0); # 1 class Bar is Foo { } Bar.new.process_data(0); # dies[1] What??? I didn't change anything yet! Why does it die? (This is the first principle in the journal entry you quoted) Let's presume that I want to extend Foo by adding a method completely unrelated to process_data, and I would like its behavior to stay the same for process_data. How would I do that? Luke [1] Well, it wouldn't, since for Liskov sanity we require that a method of the same name already exists. Let's say that Foo's parent class implemented submethod help_process_data($data) { die }.
Re: Why submethods
Luke, On Oct 29, 2005, at 3:42 PM, Luke Palmer wrote: Another thing that scares me with the utility sub point of view follows: class Foo { method process_data($data) { $.help_process_data($data); } submethod help_process_data($data) { $data+1; } } Foo.new.process_data(0); # 1 class Bar is Foo { } Bar.new.process_data(0); # dies[1] What??? I didn't change anything yet! Why does it die? (This is the first principle in the journal entry you quoted) This is true, but I think that it is easily rectified. A submethod is said to have an implicit next METHOD unless $?SELF.class =:= $?CLASS I think we could add onto that and say that in addition to checking the invocant's class, we could also check the calling context, and do like we do with private methods, and allow things like this to Just Work. However, it could also be that the creator of Foo did not intend for subclasses to be able to Just Work, and that the whole idea of Foo is to do a Template Method style pattern in which subclasses must implement the help_process_data submethod in order for things to work. This is an entirely valid usage for a submethod, and in fact, I think it is an excellent way for implementing the Template Method pattern. It is also possible that we could bring over the role idea of required methods and have the same basic principle relate to classes and submethods. If marked as such, a submethod is required to be implemented by a subclass, or class composition fails. I think that could be a useful feature which would allow very safe re-use along those lines. Anyway, just my 2 cents. Stevan