On Jul 13, 2005, at 4:35 PM, chromatic wrote:
On Wed, 2005-07-13 at 16:07 -0400, David Storrs wrote:
My understanding is that a Role is an abstract (i.e. cannot be
instantiated) blob of methods and, possibly, data. The purpose of a
Role is to paste it into a class--in other words, a Role is a not a
type, it is a part of a type.
Nope, it's a type. What is a type besides a named blob of methods
and,
possibly, data?
A label that says how the data is stored internally. For example,
compare "Int" and "int". The former is a type and a blob of methods
and not necessarily abstract. The second is a type, is NOT a blob of
methods, and is definitely NOT abstract.
That was part of why I was careful to say "an ***abstract**** [...]
blob of methods...." (Emphasis added.)
The point of this is to force the programmer to give a reasonable
constraint...when they expect something that Wags, does it need to be
a Dog, or will any Animal that can Wag be sufficient? Or are they
really looking for absolutely anything that is capable of Wagging?
The latter.
Fine. Make them say that, then. Making people think about what they
really want is a good idea.
As soon as you require signatures to enforce *how* the arguments
fulfill
a type constraint, you've violated a principle design goal of roles,
namely that it's more important that something fulfills the
requirements
of type ("RobotDog understands bark() in the context of Doglike, not
Treelike") than that it fulfills the requirements of the type by
inheriting from a base class, delegating to a contained object,
applying
a role, or whatever other way you can imagine.
That's a reasonable point. However, I wasn't deliberately using
'does Bark' to mean 'has been composed with the role Bark'. I was
using it to mean "is able to perform the interface specified by
Bark". So, if you prefer, I'll invent a new term: isableto. (Which
I think is a lousy choice for the term, but I don't care what color
that bike shed is.)
Note that there are two subtly different kinds of type constraints
under discussion: the first is what class something is, and the
second is what behavior it can exhibit. The two are very slightly
different:
multi foo(Dog $x); # Must be of class
Dog, or a class that is a descendant of Dog
multi foo(Dog $x where { not $x.feral }); # Must be of
anonymous class "class Dog (or descendant) with $.feral set to false"
multi foo(Dog isableto Bark); # Must be of class
Dog (or descendant), and must be able to Bark
multi foo(Object isableto Bark); # Absolutely any
object so long as it can Bark...how it does that is up for grabs,
though.
multi foo( isableto Bark); # Same as previous
The distinction I'm drawing is between pure behavior and behavior
+state. I'm drawing this based on the idea that Roles are not
allowed to have state--that they are pure virtuals, only used for
defining interface. If that is not true, then (A) I apologize for
the wasted bandwidth and (B) I'd like to have it explained what Roles
offer that justifies their existence, since they won't be anything
but a restricted form of a class.
--Dks