Austin Hastings wrote: > Jonathan Lang wrote: > > Austin Hastings wrote: > > > This kind of granularity does kind of imply a JavaScript-like > > > ability to compose objects, too, no? (If you can compose > > > requirements atomically, why not compose capabilities, too?) > > > > > > my $photon does Particle does Wave {...} = spark(); > > > > That's where C<but> comes in: > > > > my $photon but does Particle does Wave {...} = spark(); > > > > would be equivelent to something like > > > > class _anonymous_photon does Particle does Wave {...} > > my _anonymous_photon $photon = spark(); > > Is that ['but'] really necessary?
Maybe; maybe not. How about this: When you apply C<does> directly to an object, the result is that the object's class is changed to a singleton class identical to its previous class except that it also C<does> the specified role. When you apply C<but> to an object, the result is that the object's class is changed to a singleton class that C<is> its former class and C<does> the specified role. That is, you use C<but> when you want the new role's methods to take precedence over the existing class methods, and you use C<does> when you want the existing class methods to take precedence over the new role's methods. In the case of C<does>, you also need to be able to specify any neccessary glue code (for conflict resolution, and/or to satisfy any demands of the new role that otherwise wouldn't be satisfied). > > > > Also: in the first of these two, would classof($thingie) actually > > > > have to have Stringify as a role, or would it be reasonable to > > > > instead say that classof($thingie) must meet Stringify's demands? > > > > The latter would require more work on the compiler's part, but > > > > would be considerably more flexible. > > > > > > I prefer the latter. I want to be able to compose requirements on > > > the way. I certainly don't want to have to rewrite the core > > > libraries (or extend them all) just to mix in an interface role that > > > they already satisfy. > > > > In principle, I agree with you; in practice, it may not be workable. > > Verification should be just as easy for this as for a typed referenced > parameter. I don't see why it wouldn't be workable. It isn't neccessarily because validation would be difficult; although we _are_ saying that validation would require you to do a point-by-point comparison of the object's available methods to the role's available methods rather than simply checking to see if the object's class has the role itself[1]. Just as important as this point is the fact that sometimes you'll actually want to validate against the literal presence or absence of the role itself in the object's class, rather than whether or not the class meets the role's demands - largely because roles can supply methods as well as demanding them, and by asking for that role you're actually saying that you want the class to use that role's semantics as well as syntax. Thus my suggestion that the default be that if you ask for a particular role in a signature, it will match any class that does that particular role; if you ask for something _like_ that particular role, it will match anything that meets that role's demands whether or not it actually does the role. So saying "($thing does Dog)" would require that $thing C<does> Dog; saying "($thing like Dog)" would require that $thing satisfy Dog's demands. What you're asking for would still be available; just not through C<does>. > > How would you handle the following: > > > > role Dog {must bark();} > > role Tree {must bark();} > > > > class crossPerson { > > method bark() {speak_sharply;} > > } > > > > class Trog does Tree does Dog { > > method bark() {bark_like_a_trog;} > > } > > > > multi sub purchase(Dog $mansBestFriend) {...} > > multi sub purchase(Tree $shrubbery) {...} > > multi sub purchase($noisemaker must bark()) {...} > > > > my crossPerson $jack; > > purchase $jack; > > > > my Trog $spot; > > purchase $spot; > > > > Which, if any, of the subs should be called in each case? Or should > > the compiler complain of duplicate definitions? > > $jack is a crossPerson, which absolutely does NOT have the Dog or Trog > or Tree classes in its C<isa> chain. Of course not; nothing will have Dog or Tree in their C<isa> chain, because Dog and Tree are roles, not classes. > If Dog and Tree are both "inferred" or "inferrable" classes, then the > two multi declarations (Dog and Tree arguments) are identical. In this example, there's no difference between the Dog and Tree roles; however, this would almost certainly not be the case most of the time - at the very least, a class with a Dog role would have @.legs, while a class with the Tree role would have @.branches. However, if all that happens when you specify a demand for the Dog role in a signature is that the object must meet Dog's demands, then both crossPerson and Trog will be accepted. [1] It gets even messier because what you're really after is whether or not a specific syntax is legal for the object in question; it's entirely possible for a routine that's defined seperately from the object's class to allow the syntax to work. Using C++ pseudocode as an example, class istream { istream operator << (string s); }; and istream operator << (istream& i, string s); both allow you to use the syntax i << s; But the latter definition does so without touching the class definition; so there's no way even in principle of learning of its existence by looking at the class. ===== Jonathan "Dataweaver" Lang __________________________________ Do you Yahoo!? Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes http://hotjobs.sweepstakes.yahoo.com/signingbonus