Re: Roles and Trust
Ovid <[EMAIL PROTECTED]> writes: > --- Piers Cawley <[EMAIL PROTECTED]> wrote: >> >> How about: >> >> my method SCALAR::attributes($self:) { $$self } >> my method HASH::attributes(%self:) { %self.kv } >> my method ARRAY::attributes(@self:) { [EMAIL PROTECTED] } >> >> method _attributes($attrs) { >> my @attributes = $attrs.attributes >> return @attributes[0] if @attributes == 1; >> ... >> } >> >> Assuming it's legal. > > Just saw this. Sorry for the late reply. > > At first that gave me the willies, then I noticed the "my" on the > front. I assume because of the "my" on there that this would affect > those data types only locally? That seems like it would be a nice > compromise. > > Is this legal syntax? After some discussion on #perl6, we thought probably not (unless @Larry rules otherwise). However, my multi attributes( Scalar $scalar: ) { $$scalar } my multi attributes( Hash %hash: ) { %hash.kv } my multi attributes( Array @array: ) { [EMAIL PROTECTED] } definitely is legal (though it does rather suffer from the end-weight problem to my way of thinking). -- Piers Cawley <[EMAIL PROTECTED]> http://www.bofh.org.uk/
Re: Proposal to make class method non-inheritable
Brent, On Oct 11, 2005, at 8:17 PM, Brent 'Dax' Royal-Gordon wrote: Stevan Little <[EMAIL PROTECTED]> wrote: I would like to propose that class methods do not get inherited along normal class lines. I think you're not thinking about many major usage cases for class methods. Actually I have considered many common usages including those which you describe below, and it is my belief that only a few are truly valid uses and not abuses of class method functionality. What I kept coming back to was that pretty much all the *abuses* of class methods were better done in some other way, and that even the *valid* uses were nothing more than design choices, and could be accomplished in some other manner. For one example, look at my Cipher suite. (It's in Pugs's ext/Cipher directory.) The Cipher base class implements most of the visible API, while subclasses simply override a few internal methods; Cipher turns the wide-ranging, convenient external API into a smaller, more easily implementable internal API. Your internal API and your external API have little to do with one another as far as I can tell. The external API is simply a set of convenience functions which create instances of your classes in various ways (very cool ways I might add, especially the functional API, very nice stuff). However, you could easily remove external API, and your internal API would not really suffer, it would only require that the user manually create what your class methods create for you. While many people think Factories are many times overkill (me among them), what you are doing is a perfect candidate for the Factory pattern. In fact, one could say you are already doing an ad-hoc Factory pattern with your inheritable class methods. Some of Cipher's methods are class methods, including the pseudo-procedural .encipher/.decipher and the pseudo-functional .encipherer/.decipherer methods. These methods are included specifically *to* be inherited. Your documentation says the following things: The Cipher API's procedural interface is good enough for many purposes. Although the interface is said to be procedural, it is invoked via two class methods. The Cipher API is fundamentally object-oriented; the procedural and functional interfaces are layers on top of the object-oriented backend. Both indicate to me an acknowledgment that you are knowingly abusing the inheritance of class methods to make your functional and procedural APIs work. Now, please don't take this as an insult or slam of some kind. All good programmers know when to abuse language elements to get what they need. However, I am of the opinion that maybe we should leave these old idioms/abuses aside. In my opinion, class method inheritance is an important part of class-based OO--almost as important as object method inheritance. I disagree with you on this point (of course, otherwise I would not have started this thread), but I will admit that inheritable class methods are a very common OO idiom, and that fact (good or bad) should be taken into account. Removing features simply because their implementation is inconvenient is not The Perl Way. If it were, Perl 6 would be Java With Sigils. To be honest, the implementation is not inconvenient at all, in fact I have already done it twice (correctly at least, the meta-model currently has inheritable class methods, but the implementation is crap). 1) A Mini-MetaModel with Eigenclasses http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ MiniMetaModel_w_eigenclasses.pl Whenever I am doing something which has the potential to dig deeply into the core of the meta-model, I do it first with a Mini-MetaModel. (The MMM (mini-meta-model) is a small self-bootstrapping single- inheritance meta-model in under 2-300 LOC and usually which tends to be much easier to "mess with" than the real meta-model.) If you look at the "new" method in Class, you will see it creates an Eigenclass for each class (this is where the class methods get stored), then adding class methods is accomplished with the "add_singleton_method" method. You will find a number of tests towards the bottom of the file which demonstrate the inheritance of the class methods. 2) By using a subclass of Class http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 37_inherited_class_methods.t I did this test at autrijus's request, it creates a "ClassWithInheritedClassMethods" class which is a subclass of Class. If you create your classes (Foo, Bar, what have you) using "ClassWithInheritedClassMethods", then you can add class methods, again with the "add_singleton_method", and they are inherited correctly by subclasses. The code to make "ClassWithInheritedClassMethods" work is only 10 lines long, so as you can see the implementation is not difficult or inconvenient at all. To properly implement this in the current meta-model pr
Re: Proposal to make class method non-inheritable
All - I'm partly to blame for this thread because I put the idea into Steve's head that class methods being inheritable may be dogma and not a useful thing. Mea culpa. That said, I want to put forward a possible reason why you would want class methods to be inheritable - to provide pure functions. If we go back to every function/method/subroutine being behavior, it's pretty evident that you need some state for that behavior to operate upon. In a procedural function, the state is provided. In an object, that state is both provided and inherent in the instance the method is operating upon. In functional languages, functions maintain their own state through closures, continuations, and the like. I might want to provide in a base class a set of useful sorting routines or other such items. These would be true procedural functions and there would be a warning thrown if it accessed class state. Rob
Re: Proposal to make class method non-inheritable
Stevan Little <[EMAIL PROTECTED]> wrote: > I would like to propose that class methods do not get inherited along > normal class lines. I think you're not thinking about many major usage cases for class methods. For one example, look at my Cipher suite. (It's in Pugs's ext/Cipher directory.) The Cipher base class implements most of the visible API, while subclasses simply override a few internal methods; Cipher turns the wide-ranging, convenient external API into a smaller, more easily implementable internal API. Some of Cipher's methods are class methods, including the pseudo-procedural .encipher/.decipher and the pseudo-functional .encipherer/.decipherer methods. These methods are included specifically *to* be inherited. In my opinion, class method inheritance is an important part of class-based OO--almost as important as object method inheritance. Removing features simply because their implementation is inconvenient is not The Perl Way. If it were, Perl 6 would be Java With Sigils. -- Brent 'Dax' Royal-Gordon <[EMAIL PROTECTED]> Perl and Parrot hacker
Re: multiline comments
It was just kind of a pain because you had to put a "=cut" after the "=end", and because you had to put paragraph spaces between everything. We're getting rid of both of those restrictions. Excellent! That's what was really bugging me. I'm really glad that is changing :) Thanks, Alfie
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On 10/12/05, Rob Kinyon <[EMAIL PROTECTED]> wrote: > Plus, I can't imagine that a reverser for Parrot code is going to be that > hard to > write. Disassembling register machine code is significantly more difficult than disassembling stack machine code. That said, if the level of introspective capabilities is high, then disassembling is probably not hard. As far as I know, keeping introspective capabilities high is a major Perl goal :-) > Alternately, maybe you have a pragma that says "Finalize all classes > unless I specify that it should remain open." That's the plan, where the pragma is only available before any modules are loaded, IIRC (this keeps modules from closing themselves off). I think this is an opportune time for me to express that I think the ability to close-source a module is important. I love open source, and I couldn't imagine writing anything by myself that I wouldn't share. But in order for Perl to be taken seriously as a commercial client-side language, it must be possible to close the source. I started writing a game with a few friends last year, and as we were picking our implementation strategy, using Perl as the primary "sequencing engine" for non-time-critical tasks was immediately discounted when I commented that anybody can look at your perl source if they want to. Of course, there is no argument there for allowing closed-source *modules*, just complete applications. But I'm sure you could fish one out involving dynamic loading, or modding, or whatever you want to call it. Luke
Re: Complex types
Larry Wall wrote: On Thu, Oct 13, 2005 at 09:43:15AM +1300, Sam Vilain wrote: : Hi all, : : Is it intentional that S09 lists unboxed complex types, but equivalent : Boxed types are missing from the "Types" section in S06? Nope. As it's a trivial omission, I went ahead and changed S06.pod (r6201). Thanks, /Autrijus/
Re: Complex types
On Thu, Oct 13, 2005 at 09:43:15AM +1300, Sam Vilain wrote: : Hi all, : : Is it intentional that S09 lists unboxed complex types, but equivalent : Boxed types are missing from the "Types" section in S06? Nope. Larry
Re: Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On 10/12/05, chromatic <[EMAIL PROTECTED]> wrote: > On Wed, 2005-10-12 at 21:50 +0200, Yuval Kogman wrote: > > > This has even more implications with closed classes to which you > > don't have source level access, and if this can happen it will > > happen - i'm pretty sure that some commercial database vendors would > > release closed source DBDs, for example. > > Closed classes should not exist. > > At least, they should only exist if the person *running* Perl 6 wants > them to exist -- never if merely the class writer wants to close them. I'm not sure y'all are talking apples and apples. Yuval is talking about lack of source-level access and the class being closed. I'm not quite sure how we end up with a lack of source-level access, particularly as that locks me, the user of your module, into one specific P6 interpreter (presumably Parrot). Given the work that Autrijus and company have been doing with PIL and Pugs in general, closing the source (presumably by releasing Parrot bytecode) isn't going to really work. (Plus, I can't imagine that a reverser for Parrot code is going to be that hard to write.) Furthermore, is releasing just the Parrot bytecode going to work in multi-lingual apps? Aren't there optimizations that may not be appropriate before all the languages are known? (I'm completely out on a limb, here.) That said, I agree with chromatic closing (or finalizing) a class should be the action of the consumer, not the producer. Maybe the producer could signal his/her desire to close the class when some phase is finished. That would mean the consumer could either modify the class before that phase is finished and/or the consumer could intercept the request for finalization. Alternately, maybe you have a pragma that says "Finalize all classes unless I specify that it should remain open." Maybe, we need a negation for close? keep_open? Rob
Complex types
Hi all, Is it intentional that S09 lists unboxed complex types, but equivalent Boxed types are missing from the "Types" section in S06? Sam.
Closed Classes Polemic (was Re: What the heck is a submethod (good for))
On Wed, 2005-10-12 at 21:50 +0200, Yuval Kogman wrote: > This has even more implications with closed classes to which you > don't have source level access, and if this can happen it will > happen - i'm pretty sure that some commercial database vendors would > release closed source DBDs, for example. Closed classes should not exist. At least, they should only exist if the person *running* Perl 6 wants them to exist -- never if merely the class writer wants to close them. -- c
Re: What the heck is a submethod (good for)
On Thu, Oct 13, 2005 at 05:42:31 +1000, Damian Conway wrote: > Luke wrote: > > >Okay, I seriously have to see an example of a submethod in use. > > class Driver::Qualified { > method drive { > print "Brrrm brrrm!" > } > } > > class Driver::Disqualified is Driver { > submethod drive { > die .name(), " not allowed to drive" > } > } > > class Driver::Requalified is Driver::Disqualified {} This is not obvious that the behavior is modified, and it makes other subclasses, like Driver::Disqualified::Drunk and Driver::Disqualified::Suicidal causes the above design choice to make you either update Driver::Requalified and Driver::Disqualified to regular methods, or duplicate code in Driver::Disqualified::*. That much aside, this is not a real world example. Can you try to think of one that really applies? Looking at my past $work projects I can't think of a single instance where submethods would help me code better. On the other hand roles & mixin inheritence, private attributes that don't conflict with other private attributes of the same name, better polymorphism, better introspection, and a metamodel could have helped a lot in many places. This has even more implications with closed classes to which you don't have source level access, and if this can happen it will happen - i'm pretty sure that some commercial database vendors would release closed source DBDs, for example. -- () Yuval Kogman <[EMAIL PROTECTED]> 0xEBD27418 perl hacker & /\ kung foo master: : neeyah! pgpb15yuOsYCY.pgp Description: PGP signature
Re: What the heck is a submethod (good for)
Luke wrote: Okay, I seriously have to see an example of a submethod in use. class Driver::Qualified { method drive { print "Brrrm brrrm!" } } class Driver::Disqualified is Driver { submethod drive { die .name(), " not allowed to drive" } } class Driver::Requalified is Driver::Disqualified {} my Driver $preDUI = Driver::Qualified.new(); my Driver $perDUI = Driver::Disqualified.new(); my Driver $postDUI = Driver::Requalified.new(); $preDUI.drive(); # calls &Driver::Qualified::drive $perDUI.drive(); # calls &Driver::Disqualified::drive $postDUI.drive(); # calls &Driver::Qualified::drive Damian
Re: Proposal to make class method non-inheritable
Actually, I wondered why you didn't suggest this earlier. :) I figured you were a step ahead of me: What if I want more than a boolean out of my class method? On Oct 12, 2005, at 10:27, Stevan Little wrote: Gordon, It just occurred to me that the system shown below could be re- written to do away with class methods entirely. class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role FeatureA {} role FeatureB {} role FeatureC {} class AB { does PlugIn; does FeatureA; does FeatureB; } class ABC { does AB; does FeatureC; } Now later on, instead of asking the PlugIn if it "supportsFeatureB", you can just see if it does the "FeatureB" role, like this: if ($host.plugInClass.does('FeatureB')) { # ... do something with FeatureB } This will work with the ABC plugin as well since AB is being treated as a role, ABC will actually consume all it's subroles, which means that ABC will DWIM too. In fact, we get even more from this system since we can check if one plug-in is capable of "doing" another, because this "just works" if ($host.plugInClass.does('AB')) { # ... } And since an example is better when it is backed up by working code, I coded this up using the current meta-model prototype. You can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- MetaModel/t/38_PlugIn_example.t Stevan On Oct 12, 2005, at 9:41 AM, Stevan Little wrote: class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role SupportsFeatureA { # yes, this Role has a "class method" in it, which # the consuming class will get as a "class method" method supportsFeatureA (Class $c:) { bool::true } } role SupportsFeatureB { method supportsFeatureB (Class $c:) { bool::true } } class AB { does PlugIn; does SupportsFeatureA; does SupportsFeatureB; } role SupportsFeatureC { method supportsFeatureC (Class $c:) { bool::true } } class ABC { does AB; does SupportsFeatureC; } — Gordon Henriksen [EMAIL PROTECTED]
What the heck is a submethod (good for)
Okay, I seriously have to see an example of a submethod in use. BUILD etc. don't count. Why? Because: class Foo { method BUILD () { say "foo" } } class Bar is Foo { submethod BUILD () { say "bar" } } class Baz is Bar { } Foo.new; # foo Bar.new; # foo bar Baz.new; # foo bar If the submethod property of BUILD were actually doing anything, then we should expect it to read like this: Foo.new; # foo Bar.new; # bar Baz.new; # foo So I don't see how the constructor is a submethod[1]. And I can't come up with any examples of where I would want to use a submethod. Can someone else? Luke [1] Yes, yes, I understand that .new is calling BUILDALL, which is then calling the BUILDs individually. I'm saying that the fact that BUILD is a submethod isn't changing anything one bit.
Re: Proposal to make class method non-inheritable
On Wed, 2005-10-12 at 12:00 -0400, Stevan Little wrote: > Usefulness aside, why do Roles and Classes need to be seperate > beasts? In the current meta-model prototype, the role system is laid > atop the class system so that the following is true: > > Class is an instance of Class > Role is an instance of Class > Class does Role > > This then means that Role also .does Role since Role is an instance > of Class (which does Role). > > It gets very cyclical, but it essentially means that all classes can > be treated as roles. This allows for all sorts of interesting things > to happen actually. I've always thought that classes were more specific than roles in that you can't apply a class to another class. (Maybe that's the wrong direction of specificity. Though I am positive that .does() is more general than .isa(), I always have to stop and think about which direction co- and contra-variance goes.) Certainly I think declaring a class should imply a role of the same name, even if you can't actually apply that role and mix in state and behavior. > I have to admit though, that this comes directly from Scala (so maybe > we are not alone here out on the edge :) I've also heard that Sather does something similar but don't know any details. -- c
Re: Proposal to make class method non-inheritable
On Oct 12, 2005, at 09:41, Stevan Little wrote: If you use the BUILD submethod, then you never need to worry about a that, everything is initialized for you by BUILDALL. Now, if you want to have a constructor which accepts positional arguments rather than named pairs (as the default does), then you have a valid need to override &new. Whether you should force this upon all your subclasses is a matter of opinion I think. For varying definitions of initialized. I never much cared for the bare "poke stuff straight into my instance variables" constructor along the lines of: sub new { my($class, %ARGS); return bless \%ARGS, $class; } That more or less robs the constructor of the "behavior" part of "class = state + behavior." I need an opportunity to establish my invariants. Of course, when there is no such behavior, it saves a lot of repetitive typing in the class. C# 3 is finally growing a syntax that resolves this by having the language do the repetitive typing at the call site... X x = new X{ Y = 1, Z = 2 }; means X x = new X(); x.Y = 1; x.Z = 2; And X doesn't need anything but the default constructor. Now, this is not to say that it cannot be made to do so. A slight change to the above diagram allows for inheritence of "class methods" very easily. Class ^ : eFoo<...eBar ^ ^ | | Foo<...Bar Now, method dispatch for Bar will go first to it's class (eBar), then to any superclasses (eFoo), and any of their superclasses (Class), and so on, and so forth. A better diagram of this can be found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ docs/Method_Dispatch_w_EigenClasses.jpg). This is more or less how class methods have to work. I would go a bit further, though. Too implement this: Foo : Object Foo : Bar The runtime should use an inheritance tree as such: Object Class : Object Foo : Object Bar : Foo _Object : Class _Class : _Object _Foo : _Class _Bar : _Foo Note that every declared class, including Object and Class themselves, have an anonymous Class subclass that precisely parallels the declared inheritance chain. (Chicken and egg problem? Probably. Object and Class are Special.) With this implementation, there are three places to put state: In MyObject (instance variable), in _MyObject (class instance variable), or outside of any instance (class variable). The class instance variable is the least useful of the three. Note: I don't see much value in invoking class methods through instances, since a Foo IS_NOT_A Class. If one wants to save the user typing ".class" when invoking class methods through an instance, I would tend toward resolving it as such: class Foo { class_method int Bar(int i) { return i * i; } } -- BECOMES -- # Common interface for Foo's class methods. interface _IFoo { method int Bar(int i); } # The anonymous Class. class _Foo extends Class implements _IFoo { int Bar(int i) { return i * i; } } # The visible class. class Foo implements _IFoo { # Forwards the call to the Class. void Bar(...) { return this.Class.Bar(...); } } I'll leave the probably obvious role-based interpretation of this to those versed in such. :) And I'm going to shut my yap, now, having butted into the middle of a discussion of a hopelessly complex runtime that I haven't been following for a 18 months. :) — Gordon Henriksen [EMAIL PROTECTED]
Re: Sane (less insane) pair semantics
Hi, TSa wrote: > Ingo Blechschmidt wrote: >> Exactly. I'd like to add that, under the proposal, you always know >> what things are passed how, only by looking for a "*". >> >> foo $var;# always positionally, even if $var isa Pair >> foo *$pair; # always named > > But where is the name? Is it 'pair'? Like in > >foo :pair($pair); No. > or dynamically through > >foo $pair.key => $pair.value; Yep. > assuming that precedence of => is tighter than foo's. I think it is. > As I lengthyly ranted elsewhere in this thread the splat should just defer the > structural callability check until runtime. Well, and since everybody > seems to be happy with .$pair denoting a call through a hardref stored > in $pair, I don't understand why :$pair is not (yet) denoting a hard > pairref. Both forms beeing interpreted in the context of the term to Um, sorry, I don't understand... The only syntax I know of where a $ follows a . is calling method references: my $meth = method (Foo $self: ...) {...}; $foo.$meth(...); (But this syntax doesn't have, obviously, anything to do with magical/non-magical pairs.) > If full uncertainty isn't your thing, you might instruct the type > system to make sure that $pair at least doesn't fail you on pairhood > >my Pair $pair; Yep. >foo $pair; # syntactically an item, thus a positional call >foo *$pair; # guarranteed pair after splatting >> foo [EMAIL PROTECTED]; # always positionally > > This makes perfect sense to me if you mean that the positionals > that foo requests are satisfied in the order provided by @array > without exceptions for pairs, not to mention subtypes of pairs > or things that do the Pair role etc. Yep, it's very important that Pairs are not exceptions. >> foo *%hash; # always named (hash keys taken as parameter names) > > So that shall fail at compile time if foo has *anonymous* positionals? Assuming that anonymous positionals exist, yes, I think so. >> Previously, you wasn't able to know whether you passed something >> positionally or by name: >> >> sub bar ($x) { grtz $x } >> bar 42; # 42 passed to &grtz positionally >> bar a => 42; # either the pair (a => 42) passed to &grtz >> # positionally or the number 42 passed by name >> >> Under the new proposal, "grtz $x" always passes $x positionally. You >> don't need &grtz's signature, nor do you need to know $x's type (is >> $x a Pair?). > > Yep. But you could attempt to dispatch .key on $x in grtz: > > sub grtz ($item) > { >say $x.key; > } > > and get a printout of 'Undef of Key' or so and 'a' respectively. > HiHi, or a 'method not understood' exception if .key is not applicable > to 42 ;) Yep, of course. Pairs are, when not splatted with *, normal instances of normal classes. (And when pairs are splatted, they are no longer pairs, but syntactical constructs. (This might of course be implemented using some class in the compiler, but this is an implementation detail.)) > Stuart Cook wrote: >>>And look, if you really wanted to, you could define your own >>>splat-style operator that works exactly as you describe. But I don't >>>think it should be the default. > > I think that is difficult *without* parser support because > a purely prefix thingy doesn't get the coderef the flattened > array goes to. Right, also &prefix:<*> can be faked as a normal subroutine (the PIL to JavaScript compiler does this currently [1]), it has to be some kind of grammatical rule or perhaps a macro if we want it to be implemented properly. >> Right. Under the proposal, you can -- *if you want to* -- use pairs >> stuffed in arrays as named arguments: >> >> foo *hash(@array_of_pairs); >> # @array_of_pairs's pairs used as named args > > This hash function there is hardly the same as the one from S06, that > takes every other pair from @array_of_pairs, converts *the pair* > to a key---which might preserve the key actually---and combines it > with the next entry from the array as value? Hm. I thought the hash() sub would be a bit more DWIMmy, so it can be used for desugaring: my %hash = (a => 1, "b",2, "c"); # desugared to my %hash = hash(a => 1, "b",2, "c"); # which means my %hash = (a => 1, b => 2, c => undef); # thus: sub hash ([EMAIL PROTECTED]) returns Hash { my %hash; while shift @things -> $thing { given $thing { when Pair { %hash{$thing.key} = $thing.value } default { my $value = shift @things; %hash{$thing} = $value; } } } %hash; } But, looking at S06, the reference implementation of S06 isn't that DWIMmy. Dunno whether this is simply a oversight in S06 or whether it has been purposefully left out. >@AoP = (a => 'a', b => 'b', c => 'c', d => 'd'); >%hash = hash @AoP; ># = (AoP[0] => AoP[1], AoP[2
Re: Roles and Trust
--- Piers Cawley <[EMAIL PROTECTED]> wrote: > > How about: > > my method SCALAR::attributes($self:) { $$self } > my method HASH::attributes(%self:) { %self.kv } > my method ARRAY::attributes(@self:) { [EMAIL PROTECTED] } > > method _attributes($attrs) { > my @attributes = $attrs.attributes > return @attributes[0] if @attributes == 1; > ... > } > > Assuming it's legal. Just saw this. Sorry for the late reply. At first that gave me the willies, then I noticed the "my" on the front. I assume because of the "my" on there that this would affect those data types only locally? That seems like it would be a nice compromise. Is this legal syntax? Cheers, Ovid -- If this message is a response to a question on a mailing list, please send follow up questions to the list. Web Programming with Perl -- http://users.easystreet.com/ovid/cgi_course/
Re: Sane (less insane) pair semantics
HaloO, Ingo Blechschmidt wrote: Exactly. I'd like to add that, under the proposal, you always know what things are passed how, only by looking for a "*". foo $var;# always positionally, even if $var isa Pair foo *$pair; # always named But where is the name? Is it 'pair'? Like in foo :pair($pair); or dynamically through foo $pair.key => $pair.value; assuming that precedence of => is tighter than foo's. As I lengthyly ranted elsewhere in this thread the splat should just defer the structural callability check until runtime. Well, and since everybody seems to be happy with .$pair denoting a call through a hardref stored in $pair, I don't understand why :$pair is not (yet) denoting a hard pairref. Both forms beeing interpreted in the context of the term to their *immediate* left which in turn is interpreted leftwards. And both forms fail if the assumptions about the type of value $pair will eventually refer to won't hold. The difference to the splat form is eagerness: foo :$pair; # eager foo *$pair; # lazy and op versus sigil foo : $pair; # syntax error like $ pair foo (: $pair); # same foo:$pair; # labeled statement foo * $pair; # infix foo (* $pair); # prefix (foo *) $pair; # postfix, which I guess doesn't exist If full uncertainty isn't your thing, you might instruct the type system to make sure that $pair at least doesn't fail you on pairhood my Pair $pair; foo $pair; # syntactically an item, thus a positional call foo *$pair; # guarranteed pair after splatting But of course the call could still fail because there is no parameter under the key of $pair. Now I think you could instruct the kind type system also to oversee the meeting of this constraint with my Pair of foo $pair; foo $pair; # you guessed it, positional call foo *$pair; # always delivers $pair.value into $pair.key # parameter of foo Which might be a too sophisticated variable for your purposes if it also oversees the values to put into $pair depending on the current key. This might reduce usability of $pair while you are not calling foo with it. Thus an intermediate choice could be my Pair where .key of foo $pair; # my $pair is Pair where .key of foo; # same # my Key of foo $pair; # abbreviation of same? foo *$pair; # name hits home, but type error is possible If you know that all named params of foo are integers you could oblige yourself to adhere to this with my $pair is Pair of Int where .key of foo; And yes, I know that this should be written my $pair is Pair of Int where { .key of foo }; where the ; might be optional. Is it? The unsigiled foo there is actually shying away from full dynamism: &foo *$bar; This is almost meaningless in itself because it states: "Try to do what &foo tells you to do with whatever you find in $bar when you try to do so." But the code that the compiler generates is actually quite short! E.g. a single call instruction if &foo and $bar are already in VM registers. Only the outcome is uncertain ;) foo [EMAIL PROTECTED]; # always positionally This makes perfect sense to me if you mean that the positionals that foo requests are satisfied in the order provided by @array without exceptions for pairs, not to mention subtypes of pairs or things that do the Pair role etc. foo *%hash; # always named (hash keys taken as parameter names) So that shall fail at compile time if foo has *anonymous* positionals? E.g. a sig ($,$,$) or would there be a desparate attempt to call it as foo %hash<0>, %hash<1>, %hash<2>; or aiming at whatever .[Int] means on a hash: foo %hash[0], %hash[1], %hash[2]; BTW, I would write a keyed sig as &foo:(:x,:y,:z). Previously, you wasn't able to know whether you passed something positionally or by name: sub bar ($x) { grtz $x } bar 42; # 42 passed to &grtz positionally bar a => 42; # either the pair (a => 42) passed to &grtz # positionally or the number 42 passed by name Under the new proposal, "grtz $x" always passes $x positionally. You don't need &grtz's signature, nor do you need to know $x's type (is $x a Pair?). Yep. But you could attempt to dispatch .key on $x in grtz: sub grtz ($item) { say $x.key; } and get a printout of 'Undef of Key' or so and 'a' respectively. HiHi, or a 'method not understood' exception if .key is not applicable to 42 ;) Compare this with the old semantics: grtz $x; # $x is not a Pair? ==> $x passed positionally # else ==> # &grtz expects a Pair as its first positional parameter? # ==> $x passed positionally # else ==> # &grtz's signature lists a parameter named $x.key? #==> $x.value passed by name # else # ==> $x passed positionally Stuart Cook wrote: And look, if you really wanted to, you could define your own splat-style operator that works exactly as you describe. But I don't think it shoul
Re: Proposal to make class method non-inheritable
Gordon, On Oct 12, 2005, at 11:04 AM, Gordon Henriksen wrote: On Oct 12, 2005, at 09:41, Stevan Little wrote: If you use the BUILD submethod, then you never need to worry about a that, everything is initialized for you by BUILDALL. Now, if you want to have a constructor which accepts positional arguments rather than named pairs (as the default does), then you have a valid need to override &new. Whether you should force this upon all your subclasses is a matter of opinion I think. For varying definitions of initialized. I never much cared for the bare "poke stuff straight into my instance variables" constructor along the lines of: sub new { my($class, %ARGS); return bless \%ARGS, $class; } Yes, that is a horrible idiom which I hope will die in Perl 6. That more or less robs the constructor of the "behavior" part of "class = state + behavior." I need an opportunity to establish my invariants. Well that is where BUILD comes in, you can do all sorts of mangling of parameters in BUILD so that it does what you want it to, there is no real need to put this behavior into &new. Of course, when there is no such behavior, it saves a lot of repetitive typing in the class. C# 3 is finally growing a syntax that resolves this by having the language do the repetitive typing at the call site... X x = new X{ Y = 1, Z = 2 }; means X x = new X(); x.Y = 1; x.Z = 2; And X doesn't need anything but the default constructor. Yes, this is exactly what the &new -> CREATE -> BUILDALL -> BUILD chain is doing too. Now, this is not to say that it cannot be made to do so. A slight change to the above diagram allows for inheritence of "class methods" very easily. Class ^ : eFoo<...eBar ^ ^ | | Foo<...Bar Now, method dispatch for Bar will go first to it's class (eBar), then to any superclasses (eFoo), and any of their superclasses (Class), and so on, and so forth. A better diagram of this can be found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/ docs/Method_Dispatch_w_EigenClasses.jpg). This is more or less how class methods have to work. I would go a bit further, though. Too implement this: Foo : Object Foo : Bar The runtime should use an inheritance tree as such: Object Class : Object Foo : Object Bar : Foo _Object : Class _Class : _Object _Foo : _Class _Bar : _Foo Note that every declared class, including Object and Class themselves, have an anonymous Class subclass that precisely parallels the declared inheritance chain. (Chicken and egg problem? Probably. Object and Class are Special.) This is pretty much the same thing that I am describing, except that I don't think that Class needs an anon-class/eigenclass. All object models need a cycle at the top, this keeps the "turtles-all-the-way- down" problem away. The usual place is to put the cycle in Class (Class is an instance of Class). If you add that anon-class, you break the cycle. With this implementation, there are three places to put state: In MyObject (instance variable), in _MyObject (class instance variable), or outside of any instance (class variable). The class instance variable is the least useful of the three. Well, I would argue that class instance variables are very useful, since that is where methods and attribute meta-objects are stored. But I think users should not have direct access to class instance variables. But yes, other than that you are correct. Note: I don't see much value in invoking class methods through instances, since a Foo IS_NOT_A Class. If one wants to save the user typing ".class" when invoking class methods through an instance, Yes, that is bad, another nasty p5 idiom I hope will go away. I would tend toward resolving it as such: class Foo { class_method int Bar(int i) { return i * i; } } -- BECOMES -- # Common interface for Foo's class methods. interface _IFoo { method int Bar(int i); } # The anonymous Class. class _Foo extends Class implements _IFoo { int Bar(int i) { return i * i; } } # The visible class. class Foo implements _IFoo { # Forwards the call to the Class. void Bar(...) { return this.Class.Bar(...); } } I think we can leave the interface part out, but yes, this is basically how the eigenclasses work :) I'll leave the probably obvious role-based interpretation of this to those versed in such. :) s/interface/role/ and you have the role based version ;) Stevan
Re: Proposal to make class method non-inheritable
Gordon, On Oct 12, 2005, at 10:48 AM, Gordon Henriksen wrote: Actually, I wondered why you didn't suggest this earlier. :) I figured you were a step ahead of me: What if I want more than a boolean out of my class method? Then you put the class methods back in :) But then your Objective-C interface would need to change too. Although, the more complexity you introduce, the closer you get to the point when a Factory pattern is just as viable an approach as class methods. Stevan On Oct 12, 2005, at 10:27, Stevan Little wrote: Gordon, It just occurred to me that the system shown below could be re- written to do away with class methods entirely. class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role FeatureA {} role FeatureB {} role FeatureC {} class AB { does PlugIn; does FeatureA; does FeatureB; } class ABC { does AB; does FeatureC; } Now later on, instead of asking the PlugIn if it "supportsFeatureB", you can just see if it does the "FeatureB" role, like this: if ($host.plugInClass.does('FeatureB')) { # ... do something with FeatureB } This will work with the ABC plugin as well since AB is being treated as a role, ABC will actually consume all it's subroles, which means that ABC will DWIM too. In fact, we get even more from this system since we can check if one plug-in is capable of "doing" another, because this "just works" if ($host.plugInClass.does('AB')) { # ... } And since an example is better when it is backed up by working code, I coded this up using the current meta-model prototype. You can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6- MetaModel/t/38_PlugIn_example.t Stevan On Oct 12, 2005, at 9:41 AM, Stevan Little wrote: class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role SupportsFeatureA { # yes, this Role has a "class method" in it, which # the consuming class will get as a "class method" method supportsFeatureA (Class $c:) { bool::true } } role SupportsFeatureB { method supportsFeatureB (Class $c:) { bool::true } } class AB { does PlugIn; does SupportsFeatureA; does SupportsFeatureB; } role SupportsFeatureC { method supportsFeatureC (Class $c:) { bool::true } } class ABC { does AB; does SupportsFeatureC; } — Gordon Henriksen [EMAIL PROTECTED]
Re: Proposal to make class method non-inheritable
Larry, On Oct 11, 2005, at 8:47 PM, Larry Wall wrote: On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote: : Hello all. : : I would like to propose that class methods do not get inherited along : normal class lines. I think most class methods should be written as submethods instead. In which case they would not be inherited then. I (obviously) agree with you on that :) You seem to be arguing that a class has no state, but my view is that, in the abstract, a class encompasses the state of *all* its objects. It just hasn't picked one particular object to be at the moment. No, not that class has no state, but that with the currently specced classes we have inherited behaviors (class methods) but they do not inherit the accompanying state (class attributes) as well. I see this as potentially very problematic. : == Instance Counting Class : : The most common example given for class methods is an "instance : counter". Here is how one might (naively) look in Perl 6: : : class A { : our $.count; : method count (Class $c:) { $.count; } : submethod BUILD { : $.count++; : } : } That's obviously broken--the count accessor should be a submethod to be consistent, unless the explicit intent is that any subclass of A return the count of A's. Which, not surprisingly, is exactly what you get below. It should probably have been declared: our $.A_count; in that case. And in which case you don't need the explicit accessor, since one would have been provided because of the dot. If you don't want the autoaccessor, don't use the dot. Yes, this example was purposefully broken, but also copied from several tutorial on "how to use class methods". I suppose an argument could be made that autoaccessors for class vars should be submethods by default. Or maybe "my $.count" makes a submethod, while "our $.A_count" makes a method. I think that is probably not a bad idea. If we not going to inherit the class state, then we should not inherit the class method either. : Clearly, we only have one instance of A, and one instance of B, so : those numbers are wrong. It could be argued that since B is a subtype : of A, we do have two A's, but the argument does not work in reverse. Sure it does. It doesn't matter whether B is a subtype of A or not, you've given it an interface to code that counts A's. True, that was probably a bad example (culled from other bad examples). : But either way, I would argue that the results shown above are : misleading, and probably not what the programmer intended. That's certainly possible, but it wouldn't be the first time people have been surprised that the computer did exactly what they asked it to... :-) Also very true. : Sure, you could do that, however, it complicates the meta-model : unnecessarily. It is much easier to accomplish this using a subclass : of Class. : : class CountingClass is Class { : has $.counter; : method count (CountingClass $c:) { $.counter; } : method new (CountingClass $c: %params) { : $.counter++; : next; : } : } : : class A meta CountingClass {} : class B meta CountingClass {} : : Now A and B both have their own counters neither of which interfere : with one another. Only by forcing people to repeat themselves as a matter of policy. And policy could just as easily have added "our $.count" to B. The real trick would be to set up A such that you don't have to do anything special in B. I suppose we could say that, by default, if A isa B, then A gets also gets whatever metaclass B has, not the standard metaclass supplied by "class". I considered this as well, it seems to make some sense that the metaclass of A is also the metaclass of B if A isa B. This would actually simplify a particular edge case with the eigenclasses that was problematic. This diagram assumes we have inheritable class methods, and they are implemented using the eigenclasses. Class ^ : eFoo<...eBar ^ ^ | | Foo<...Bar The method dispatch for Bar will go first to it's class (eBar), then to any superclasses (eFoo), and any of their superclasses (Class), and so on, and so forth. When you introduce a custom metaclass like so: Class ^ : CustomMeta ^ : eFoo<...eBar ^ ^ | | Foo<...Bar A "problem" occurs with method dispatch for Bar. First it will go to eBar, then to eFoo, then to CustomMeta, then to Class, etc, etc. Since Bar was not explicitly created with CustomMeta, this is not correct. However, if the metaclasses act as you describe, this is then does exactly what it is supposed to. I think it is a sane approach personally. But these are metaclasses, not classes. You keep writing the type of the invocant of class methods as Class, but I don't believe that anymore. Sorry, just following the A12 examples :) The type of the invocan
Re: Proposal to make class method non-inheritable
Gordon, It just occurred to me that the system shown below could be re- written to do away with class methods entirely. class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role FeatureA {} role FeatureB {} role FeatureC {} class AB { does PlugIn; does FeatureA; does FeatureB; } class ABC { does AB; does FeatureC; } Now later on, instead of asking the PlugIn if it "supportsFeatureB", you can just see if it does the "FeatureB" role, like this: if ($host.plugInClass.does('FeatureB')) { # ... do something with FeatureB } This will work with the ABC plugin as well since AB is being treated as a role, ABC will actually consume all it's subroles, which means that ABC will DWIM too. In fact, we get even more from this system since we can check if one plug-in is capable of "doing" another, because this "just works" if ($host.plugInClass.does('AB')) { # ... } And since an example is better when it is backed up by working code, I coded this up using the current meta-model prototype. You can see it here: http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/t/ 38_PlugIn_example.t Stevan On Oct 12, 2005, at 9:41 AM, Stevan Little wrote: class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role SupportsFeatureA { # yes, this Role has a "class method" in it, which # the consuming class will get as a "class method" method supportsFeatureA (Class $c:) { bool::true } } role SupportsFeatureB { method supportsFeatureB (Class $c:) { bool::true } } class AB { does PlugIn; does SupportsFeatureA; does SupportsFeatureB; } role SupportsFeatureC { method supportsFeatureC (Class $c:) { bool::true } } class ABC { does AB; does SupportsFeatureC; }
Re: Proposal to make class method non-inheritable
Piers, On Oct 12, 2005, at 5:22 AM, Piers Cawley wrote: We definitely have two instances of A since, B.isa(::A). We also have a fragile implementation of count. :) Sorry, I purposefully made it a kludge as that is usually the way the example is shown in most tutorials about class methods. class A { our %.count_of method count (Class $c:) { %.count_of{$c} } method BUILD { $class = ($?SELF.class) @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)} You can use the MRO here, which is an already linearized list of the inheritance tree (in C3 order) with all duplicates removed. for $class, [EMAIL PROTECTED] -> $c { %.count_of{$c}++ } } Where we're assuming I've got the syntax of 'for' right, and that 'ancestors' is a class method that returns all of a class's ancestors. This might not work too well in the face of a dynamic inheritance tree, but it should be possible to work around. Something like this might work: Class A { our %.instance_count_of method count (Class $c: ?$with_descendents = undef) { my @interesting_classes = $c; if $with_descendents { push @interesting_classes, *($c.all_subclasses); } [+] %.instance_count_of(@interesting_classes) } method BUILD { %.instance_count_of($?SELF.class) } } Where we're assuming that a class can find all its subclasses -- Piers Cawley <[EMAIL PROTECTED]> http://www.bofh.org.uk/
Re: Proposal to make class method non-inheritable
Gordon, On Oct 11, 2005, at 9:10 PM, Gordon Henriksen wrote: On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote: I would like to propose that class methods do not get inherited along normal class lines. You mean, make them *not methods?* Because it's not a method unless it has an invocant, as far as I'm concerned. (Method implies polymorphism.) No, they would still have an invocant. That invocant would be an anon- class which itself is an instance of Class. It works like so: (First, lets make a legend) --> is instance of ..> is subclass of NOTE: Class means the class named "Class", this distinction is important. When you create the class Foo, this is what you have: Class ^ | Foo Foo is an instance of class Class (Class itself is an instance of class Class too, but thats only slightly relevant here). When you add a class method (one which cannot be inherited), it is done with an eigenclass. This changes the above structure into this: Class ^ : eFoo ^ | Foo Now, we have created an anon-class (or eigenclass), whose entire purpose is to hold the class methods of Foo. Since the eigenclass is a subclass of Class, then all of Class's methods are inherited. This means that our method dispatcher does not need to know about class methods as a special case, as far as it is concerned, they are just normal instance methods on Foo (which itself is an instance of eFoo, which is then a subclass of Class). Now, why are they not inherited. Lets expand this diagram a little more: Class ^ +-|+ | | Foo<...Bar So Foo and Bar are both instances of Class, and Bar is a subclass of Foo. It is fairly straightforward, but now lets introduce the eigenclasses to hold class methods. Class ^ ..:. : : eFooeBar ^ ^ | | Foo<...Bar Now, method dispatch for Foo will go to eFoo (since Foo is an instance of eFoo, and method dispatch always starts at the class-of the instance), and it will continue up to Class (since Class is the superclass of eFoo). The same goes for Bar, first to eBar, then to Class. Since eFoo and eBar are not connected, then normal method dispatching does not go along those lines. Now, this is not to say that it cannot be made to do so. A slight change to the above diagram allows for inheritence of "class methods" very easily. Class ^ : eFoo<...eBar ^ ^ | | Foo<...Bar Now, method dispatch for Bar will go first to it's class (eBar), then to any superclasses (eFoo), and any of their superclasses (Class), and so on, and so forth. A better diagram of this can be found here (http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/docs/ Method_Dispatch_w_EigenClasses.jpg). : Let's start by making a very basic definition of an *object*, : ignoring any implementation details or specifics. : : object == state + behavior I don't see how this is a bad thing. Classes don't have state. That's their lot in life. Que sera! Inheritance of behavior alone is useful. Classes do have state though. They have class attributes: class Foo { our $.bar; my $.baz; } that state is just not inherited. I am not actually arguing that inheritance of just behavior is not useful, more that inheritance of behavior *without the accompanying state* is not useful, and in many cases wrong. My primary want for class methods, as a whole, is to provide this sort of interface in Objective-C: @interface Host : NSObject { - (Class)plugInClass; - (void)setPlugInClass:(Class) plugInClass; } @interface PlugIn : NSObject { - (BOOL)initWithHost:(Host *)host; + (BOOL)supportsFeatureA; + (BOOL)supportsFeatureB; } ... later ... if ([[host plugInClass] supportsFeatureA]) { ... expose UI element ... } My Objective-C is very rusty, but let met see if I understand what you are doing. Host has-a Class object, which it uses as a plugInClass. Your PlugIn then has class methods (supportsFeatureA, supportsFeatureB) which can be used by the Host to query the capabilities of its plugInClass. This type of thing could be accomplished with Roles. class Host { my $.plugInClass; } role PlugIn { method initWithHost (Host $h:) { ... } } role SupportsFeatureA { # yes, this Role has a "class method" in it, which # the consuming class will get as a "class method" method supportsFeatureA (Class $c:) { bool::true } } role SupportsFeatureB { method supportsFeatureB (Class $c:) { bool::true } } class AB { does PlugIn; does SupportsFeatureA; does SupportsFeatureB; } One could argue that it is more typing, however, I think that in the long run, it will be less typing since you never need to repeat the supportsFeatureA or supportsFeatureB method, just con
Re: multiline comments
Alfie John skribis 2005-10-12 15:28 (+1000): > Does Perl6 support multiline comments? All incarnations of Perl have allowed us to begin multiple subsequent lines with the comment glyph '#'. I am sure Perl 6 will not break this tradition. Juerd -- http://convolution.nl/maak_juerd_blij.html http://convolution.nl/make_juerd_happy.html http://convolution.nl/gajigu_juerd_n.html
Re: Proposal to make class method non-inheritable
Stevan Little <[EMAIL PROTECTED]> writes: > Hello all. > > I would like to propose that class methods do not get inherited along > normal class lines. > > I think that inheriting class methods will, in many cases, not DWIM. > This is largely because your are inheriting behavior, and not state > (since class attributes are not inheritable). Let me explain in more > detail. > > Let's start by making a very basic definition of an *object*, > ignoring any implementation details or specifics. > >object == state + behavior > > This statement assumes that *objects* at their core are a unique > state coupled with a collection of behaviors to act upon that > particular state. Of course we are ignoring all the other class/meta/ > inheritence junk for now. > > To take away the behavior, and only be left with state would degrade > our object to the level of C struct or Pascal-style record-type. To > take away the state, and only be left with behavior, would basically > leave a module/package or some pseudo-random collection of functions. > > So at this point, I think it is safe to say that an *object* should > have both state and behavior. > > Now, back down from the theoretical cloud to reality. I would like to > show some canonical class-method examples (and in some cases, show > how they are broken), then show how they might be better accomplished > in Perl 6 without the need for class methods to be inherited. > > == Instance Counting Class > > The most common example given for class methods is an "instance > counter". Here is how one might (naively) look in Perl 6: > > class A { > our $.count; > method count (Class $c:) { $.count; } > submethod BUILD { > $.count++; > } > } > > Each time an instance of A is created the counter is incremented. So > that ... > > A.count; # 0 > A.new; > A.count; # 1 > > Now this makes sense, until we subclass A. > > class B is A {} > > A.count; # still 1 > B.new; # calls A::BUILD > > A.count; # 2 > B.count; # 2 > > Clearly, we only have one instance of A, and one instance of B, so > those numbers are wrong. It could be argued that since B is a subtype > of A, we do have two A's, but the argument does not work in reverse. > But either way, I would argue that the results shown above are > misleading, and probably not what the programmer intended. We definitely have two instances of A since, B.isa(::A). We also have a fragile implementation of count. class A { our %.count_of method count (Class $c:) { %.count_of{$c} } method BUILD { $class = ($?SELF.class) @countable_ancestors = $class.ancestors.uniq.grep :{.isa(::A)} for $class, [EMAIL PROTECTED] -> $c { %.count_of{$c}++ } } Where we're assuming I've got the syntax of 'for' right, and that 'ancestors' is a class method that returns all of a class's ancestors. This might not work too well in the face of a dynamic inheritance tree, but it should be possible to work around. Something like this might work: Class A { our %.instance_count_of method count (Class $c: ?$with_descendents = undef) { my @interesting_classes = $c; if $with_descendents { push @interesting_classes, *($c.all_subclasses); } [+] %.instance_count_of(@interesting_classes) } method BUILD { %.instance_count_of($?SELF.class) } } Where we're assuming that a class can find all its subclasses -- Piers Cawley <[EMAIL PROTECTED]> http://www.bofh.org.uk/
RE: Proposal to make class method non-inheritable
On Tue, Oct 11, 2005 at 06:10:41PM -0400, Stevan Little wrote: > I would like to propose that class methods do not get inherited along > normal class lines. You mean, make them *not methods?* Because it's not a method unless it has an invocant, as far as I'm concerned. (Method implies polymorphism.) : Let's start by making a very basic definition of an *object*, : ignoring any implementation details or specifics. : : object == state + behavior I don't see how this is a bad thing. Classes don't have state. That's their lot in life. Que sera! Inheritance of behavior alone is useful. My primary want for class methods, as a whole, is to provide this sort of interface in Objective-C: @interface Host : NSObject { - (Class)plugInClass; - (void)setPlugInClass:(Class) plugInClass; } @interface PlugIn : NSObject { - (BOOL)initWithHost:(Host *)host; + (BOOL)supportsFeatureA; + (BOOL)supportsFeatureB; } ... later ... if ([[host plugInClass] supportsFeatureA]) { ... expose UI element ... } Rather than having to make plugin creation cheap so that I can do this: class Host { public Type PlugInClass { get { ... } set { ... } } } class PlugIn { public bool Host { get; } public abstract bool SupportsFeatureB { get; } public abstract bool SupportsFeatureA { get; } } ... later ... PlugIn plugIn = (PlugIn) Activator.CreateInstance(host.PlugInClass); if (plugIn.SupportsFeatureA) { ... expose UI element ... } Another alternative is to introduce a PlugInFactory. Which might be better in complex scenarios. But it's often overkill. And it's certainly more typing. In C#, I might also use attributes to decorate the plugin Type. But those, too, are more typing than class methods (and also weakly typed). Also, of course, inheriting constructors is nice. Of course, it opens up the whole "designated constructor" can of worms. But that's okay; if you're subclassing, it's your responsibility to make it work -- Gordon Henriksen [EMAIL PROTECTED]