In spite of Larry's comments, I will continue to entertain this idea until it is solid to myself that I would be comfortable accepting it.
On 12/13/06, Jonathan Lang <[EMAIL PROTECTED]> wrote:
Agreed. The question is whether you think of a role as a set of methods ("intension set") or as a set of instances ("extension set"). FWIW, it wasn't until this thread that I even registered that the latter possibility existed. Given the above contrast between roles and subtypes, I would really like to keep the extension set mindset limited to subtypes and the intension set mindset limited to roles: a role is an interface (i.e., a set of methods); a type is a set of possible instances.
Eh, a proposal is nothing if you can't make sense of it from both mindsets, because they both are real. While you may think of a role as an interface, it still does have objects that can obey it, so the set of such objects still exists. My brain seems to prefer the extensional mindset, but it's important to try to make sense of everything from both. Hmm, the extensional is the more "spookily theoretical" of the two, since Perl will know the interface, but it won't create the set of all possible, eventual instances.
> But that makes no sense at all because these are the ones which are > specialized further down in the subtyping chain. There has to be > some extra that the supertype defines for the subtypes. No, there doesn't. For example, let's assume that whoever created the Num role forgot to define an Order role for it. Supertyping would let you create that role for yourself and would ensure that it has the proper relationship with Num. That's what supertyping of roles should be about: extracting subsets of its interface for use elsewhere (which is part of the reason I'm leery about calling it "supertyping"; the important part isn't the greater number of instances that it can have, but instead the simpler interface that it provides).
Note that I *am* arguing for a back-editing behavior. You are of course allowed to remove anything (by not declaring it), and you are also allowed to add new methods as long as they have a default implementation. You are not allwed to add new unimplemented, or required, methods. The reasoning for this is mostly utility. How are you supposed to generalize Num to Complex (okay, fine, I'll try to come up with another example. Is it okay if it is also from math?) if Num didn't know that an "imaginary part" existed? You could really consider that syntax sugar if you like: role Foo { method foo() { "hello" } } role Bar superdoes Foo { method bar() { "world" } } Is equivalent to declaring Bar with no methods, and then adding: multi sub bar(Bar:) { "world" } Modulo some minor differences, but the semantics are essentially the same. I don't think we'd want to disable back-editing because then we would be encouraging the idiom I just demonstrated, which is less clear (IMO). Back-editing seems weird from an intensional mindset, but perfectly natural from an extensional mindset (you are just defining functions on things). If you don't think of a role as a set of methods, but rather a tree of sets of methods (like inheritance), then back-editing seems more natural (you just insert a different parent above the old role).
One problem with this is that the default return value for Num.im ought to be zero; the default return value for Complex.im ought to be whatever the imaginary component of the number is. So role Complex would need both method im (Complex: ) { return .im } method im (Num: ) { return 0 }
Good point. Hmm, that's a bit awkward. It can actually be averted in the Complex case, by defining the .im attribute to default to 0. But that is a hack that will not generalize. For now (because of this example, in fact), I'm inclined to change the proposal to "please don't design the language to prevent a module from implementing supertyping". I think disallowing reopening of roles will prevent that. Maybe we allow reopening of roles, but new method declarations have to come with defaults; that way you are not (as above) invalidating existing objects, just adding behavior to them. That is a tricky issue, though, because such definitions might add conflicts and invalidate those objects anyway. Maybe more-recently added methods have less priority than older ones. That stinks. Hmm. I need to think about this. Luke