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

Reply via email to