HaloO Luke,

good to hear from you again!

you wrote:
I'd tend to agree.  This is an important feature of an object system
for me,

And I hope for the rest of @Larry, too.


There is a nice duality in this specification. When you say:

   role Foo does Bar does Baz {...}

You are saying Foo = Bar (*) Baz (*) ...;  # intersection of Bar, Baz,
and the following spec

When you say:

   role Foo superdoes Bar superdoes Baz {...}

You are saying Foo = Bar (+) Baz (+) ...;  # union of Bar, Baz, and
the following spec

First of all it strikes me as odd that you have union as (+) and
intersection as (*). Is that the official definition? I would like
to see (|) and (&) because of the duality to the logical ops. Besides
the fact that (+) could mean Bag addition and (*) the cartesian
product.

Secondly I figure you are operating on the extension set a role
defines. That is union produces a supertype aka the larger set
of instances. This is in accordance to the usual type theory
approach. Note that Jonathan operates on the intension set of roles
that is union produces a subtype.


Things work a little differently for required methods.  When a
superrole requires a method be implemented, we (the language
designers) have a choise to make: it is illegal if the superrole
requires a method that the subroles don't implement or don't
themselves require, or it simply adds the new method to the required
list of the subroles which don't implement it.  I'm inclined to say
the former, even though it seems a little more brittle.

I can see no brittleness. The role that is supertyped is already
fully defined when the superrole is about to be created. Thus it can
be checked if required but unimplemented methods---that is ones with
a {...} body---are present. These should be rejected on the rational
that the pre-existing code can't retroactively be made to implement
the method.


 It means that
when you are implementing a role in a class, all you have to look at
for what you need to do is the role and the roles that it includes;
you don't need to scan the entire source for superroles which
encompass the one you are implementing.  That is the user-friendly way
to put it, but there is an analogous argument for independent
modularity (you don't want the definition of a new superrole to
invalidate objects that already exist).

Well spoken.


Things get a little tricky when you think about "does" and "superdoes" together:

   role Foo does Bar superdoes Baz {...}

What does that mean?  Okay, Foo is a subset of Bar, and a superset of
Baz.  Already by simply declaring this we have mandated that "Baz does
Bar".  If Baz doesn't already conform to the interface of Bar, Foo
better fill in the gaps for it.  As for the ..., anything which
conforms to it and Bar ought to be in Foo.  So I think the equation
ends up:

   Foo = Bar (*) (Baz (+) ...);

In words, you are a Foo if you are a Bar and you either are a Baz or
conform to my interface.

In the thread 'signature subtyping and role merging' I have argued
the need of merging method signatures that come in from different
superroles. This is less of a problem when creating superroles because
one can drop the method from the interface and maintain the subtyping
relation. So filling in the gaps is a hard task in general. I mean
in your example Foo has to define all methods required by Bar so that
Baz has at least the default provided by Foo. The gap between Baz and
Bar might also contain unresolvable name clashes that are of course
no problem as long as Bar and Baz are unrelated.


Whew, I was really only going to reply with an "I dig it" sort of
response, but I seem to have written some sort of complete theory. :-)

I missed you in the 'set operations for roles' thread. Your theory is
basically what was discussed there. Unfortunately nothing made it into
the synopsis except the dropping of '|' as the separator for
pre-composed roles. Actually not even the set operators are in S03.


A thing that is still unclear to me is how the issue of the supertype
intercepting lvalue uses of its methods is resolved. Preferably in a
declarative style. I mean a simple 'is rw' trait will hardly do because
you have to return a complete object of which only an attribute is
written to. The former subtype value has to be made available for the
lvalue method for constructing the new supertype lvalue.

Regards, TSa.
--

Reply via email to