develooper Front page | perl.perl6.language | Postings from January 2004

RE: A modest question

Thread Previous | Thread Next
Jonathan Lang
January 8, 2004 16:24
RE: A modest question
Message ID:
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

[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); 


  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

Thread Previous | Thread Next Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About