In a message dated Fri, 29 Sep 2006, Aaron Sherman writes:
First the high-level point: I'm dropping the RFC, because, as TimToady pointed out on IRC, we're not quite far enough down the line to see the breadth or certainty of the need yet.

Yes, but I don't think the conversation should stop. These are important semantics of the object model and we should be at least roughly on the same page so that when someone gets the tuits to work on it, it's clear what the direction is.

That said, this is a different point, above and I think it's an easy one to take on.

role A { method x() {...} }
class B { does A; }

does generate an error per "If a role merely declares methods without defining them, it degenerates to an interface:" from S12.

However, that's not to say that a class can't be abstract, just that a class that does an interface (a role with nothing but abstract methods) must implement the role's interface.

So why would it generate an error? Why wouldn't it merely result in B being abstract too, assuming that contra my prior mail, classes can be abstract? Do you have to be explicit about it and say

  role A  { method x() { ... } }
  class B { does A; method x() { ... } }

?  That seems un-Perlishly verbose to me; we had DRY before Ruby ever did.

Nothing is said of what happens when you compose a role that has both defined and undefined methods, but IMHO, that's at most a warning if they remain undefined after composition, since you might want to use that class as a trait at runtime where target objects will define that method.

As I said on IRC, I don't read the part of S12 you quote as being the definition of interface; I merely read it as being an analogy to the concept of interface found in other languages. I'd find it absurd if merely changing

  role Existential { method is { ... }; method isnt { ... } }

to

  role Existential { method is { ... }; method isn't { ! .is } }

resulted in the role changing its instantiability.

Certainly this:

class A { method x() {...} }

is very explicit, and should be allowed, given that it is a promise that "sometime before x is called, it will be defined." It's a runtime error if that promise is not kept.

Did you mean to have "class B" and "does A" there, as in my un-Perlish example above? If so, then see my response above. If not... I'm a little surprised. Since roles and classes share the package namespace, I wouldn't expect you to be able to declare a class with the same name as a preexisting role, even if you implemented all the role's interfaces within that class....

One more point for the hypothetical future object-model designer/implementer with the even more hypothetical tuits, so that it doesn't get lost: note that in a DBC context, { ... } is insufficient for an abstract routine. PRE and POST blocks would ordinarily be included as well. A routine missing a PRE or POST would be considered to have:

   method is {
     PRE  { True }
     POST { True }
     ...
   }

which under DBC rules would be the same as having no POST at all... but would unfortunately cause any future PREs to be ignored!

(Under design-by-contract rules, POSTs are and-ed from least-derived to most-derived, but PREs are or-ed. In fact, in Eiffel, PRE is called "require" and POST is called "ensure", but only in base classes; in derived classes, you must type "require else" and "ensure then" to make explicit that your assertions are being or-ed or and-ed with assertions elsewhere in code.)

Trey

Reply via email to