> -----Original Message-----
> From: Larry Wall [mailto:[EMAIL PROTECTED]
> Sent: Friday, December 12, 2003 8:30 PM

> On Fri, Dec 12, 2003 at 05:17:37PM -0500, Austin Hastings wrote:

> : Good. I like the mixin being available at either time. This
> makes properties
> : a lot more useful since I can provided "default" or "normal" values:
> :
> :   role Celebrated
> :     does Date
> :     does {
> :       method celebrated($d) { return $d.date; }
> :   }
> :
> :   class Birthday does Celebrated {
> :     has $.date;
> :   }
> :
> :   my Birthday $d = Birthday.new('February', 29, 2004) but
> : Celebrated('March', 01, 2004);
> :
> :   print "My birthday is celebrated $d.celebrated";
>
> More generally, you can write the rest of the class knowing that the
> role is there if it's compiled in.
>
> : I presume that the linear order (compile time) or chronological order of
> : applying roles decides the order in which overlaid methods are
> : C<wrap>ed/overlaid.
>
> The original Traits paper specifies that it's illegal to compose two
> methods of the same name into the class, and you have to rename one of
> them to get them both visible.  This is why the authors specifically
> rejected mixins, because they hide errors like this.

I'm not convinced these are errors. Having a role override methods makes
sense in a lot of ways.

Consider, for example, a caching or persistence implementation that
overrides the .STORE method of its victims.

It seems to me there's an argument both ways --

1. Code written in the absence of a role won't anticipate the role and
therefore won't take (unknowable) steps to disambiguate method calls. Ergo
method overloads are bad.

2. Roles may be written to deliberately supercede the methods of their
victims. Method overloads are vital.

This doesn't take into account role vs. role conflicts (which seem more
likely to be serendipitous).

Perhaps an "exact signature" rule would work? Such that if the method was an
exact replacement, then no error occurs, otherwise it becomes either an
error or a multi?

Alternatively, perhaps a role must declare its method to be multi or not,
and if not then the role's method overloads the original class's.

(Which takes us to retroactive multi-fication. Ugh.)

Or perhaps you just have to say "this method overloads".

> As for the relationship of "Trait" methods to other methods
> declarations, an explicit method declaration in the class proper
> overrides the composed methods, while composed methods override
> anything else in the inheritance hierarchy.

At compile time, right? Whereas composition (but=) overrides declaration at
run-time?

> : Which is it, by the way? Or is there MTOWTDI, such as a method
> modifier for
> : specifying polymorph behavior?
>
> The default way might well be the way specified in the Traits paper.
> However, their underlying language didn't support any kind of multi
> dispatch.  Perl 6 will be able to "multi" any set of names in the same
> namespace as long as the arguments are differentiable by type.  So it
> might be possible to insert a stub method declaration in the class
> proper that says "treat all composed methods of this name as multis".
> That presumes the methods take differing arguments, of course.
>
> :   method CONFORM is wrapped { ... call ... }
>
> That would be another way to do it, except that you might still have
> to switch on something to tell it which role method to call.
>
> : > A property is a simple kind of role that supplies a single attribute.
> : > The type of a property is identical to its role name.  Roles can have
> : > subtypes that function as enums when the subtypes are constrained to a
> : > single value.
> :
> : This seems really clunky for enums. It works okay for boolean, but even
> : doing month-names is going to suck pretty hard:
> :
> :   role Month;
> :
> :   role January   does Month[0];
> :   role February  does Month[1];
> :   role March     does Month[2];
> :   role April     does Month[3];
> :   role May       does Month[4];
> :   role June      does Month[5];
> :   role July      does Month[6];
> :   role August    does Month[7];
> :   role September does Month[8];
> :   role October   does Month[9];
> :   role November  does Month[10];
> :   role December  does Month[11];
> :
> :   role Month does Int[January..December];
>
> That's why I suggested some syntactic sugar for it.  But I admit that
> treating each enum as a subtype is a stretch.  They could be constant
> methods, for instance.  In any event, the various enum names should
> probably be hidden in the Month role and not be exported by default.

Yeah, the concept is useful enough that it's probably worth a spoonful of
sugar. Perhaps it were better to think of a clever way of defining a batch
of named constants in a class declaration, so that enums could be full
classes if they want to be:

  class Month is Int {
    method name {...};
    has values [ January => 0, February, ..., December ];
  }

> : > You can use one of these subtypes without specifically
> implying the role
> : name.  So saying
> : >
> : >     $bar but Red
> : >
> : > might give you a value with the property Color.
> :
> : This is smart and helpful. I like it. However, there needs to
> be a way to
> : specify what to do when multiple roles share the same values.
> For example,
> : if I have NeededBy and Estimated roles:
> :
> :   my $birthday = "02/29/2004" but March;
> :   my $ship_date = "01/01/01" but NeededBy(February);
>
> Conflicts within a class either need to be reported as soon as they're
> spotted, or dealt with by some kind of multi dispatch.  There's no hiding
> or overriding within a composed class.

This isn't hiding/overriding directly, but resolving an ambiguous value
(February) which could belong to either the NeededBy or the Estimated roles.

Consider C<green> -- does it mean Color(green) or Ripeness(green)?

> : > You can write the corresponding boolean test using the smart match
> : operator:
> : >
> : >     $bar ~~ Red
> : >
> : > and it (smartly) picks out the Color property to compare
> with, provided
> : > it's unambiguous.  You can use that syntax to compare against any
> : > subtype or junction of subtypes:
> : >
> : >     $bar ~~ Redish&Whiteish       # pinkish
> : >
> :
> : Disambiguation?
> :
> :   $bar ~~ NeededBy(February)
> :
> : or
> :
> :   $bar.NeededBy ~~ February
>
> Certainly the second form should work, unless it blows up because
> there's no NeededBy property.  Not sure about the parens on the first
> form, but there has to be some syntax that makes the type of an enum
> explicit, and that form is probably going to be preferred if the
> second form blows up on non-existent properties.  And the syntax
> needs to support something like
>
>     NeededBy[January|July]
>
> so NeededBy::January is probably not going to cut it.

Two good points.

=Austin

Reply via email to