From: Jonathan Lang [mailto:[EMAIL PROTECTED]
> Piers Cawley wrote:
> > > Why does it have to be a String, though?  What prevents it from
> > > working with anything that can stringify, besides the overly
> > > restrictive signature?  What if you could say (the Perl 6 equivalent
> > > of):
> > >
> > >   sub print_it ( does Stringify $thingie )
> > >   {
> > >           print $thingie.stringify();
> > >   }
> > >
> > > That's both more general and something more specific.  By asking for
> > > what you really want, you're not coding everyone else into a corner.
> >
> > In this particular case I prefer the Smalltalk thing of requiring all
> > objects to have a C<print_on($aStream)> method and not even requiring
> > that C<$aStream> satisfy the Stream role. But that's probably a matter
> > of taste.
>
> Maybe as an alternative to
>
>    role Stringify {must stringify();}
>    sub print_it (Stringify $thingie) {print $thingie.stringify();}
>
> you might be able to say
>
>    sub print_it ($thingie must stringify()) {print $thingie.stringify();}
>
> Hmm... there's a certain elegance to being able to specify one or two
> requirements directly in a signature.

Indeed. I like the idea of dynamic anonymous roles -- it's more behavioral
than anything else.

 sub print_it ($thingie must stringify()) {...}

Definitely gets down to the lowest level quickly, which is nice. Even nicer
is the ability to use this sort of requirement as kind of an advanced
signature: declare exactly what you're going to do. (In other words, your
signature may say

  sub foo(Object $o) {...}

because you want to accept anything in the hierarchy. But it's nice to
extend it with

  sub foo(Object $o must stringify() must isa() must typeof()) {...}


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

>
> 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.

>  Perhaps "Stringify $thingie" requires that the Stringify role must
> actually be used, while something like "$thingie like Stringify" would
> only require that Stringify's demands be met?

My thought would be that once you have an object in hand, you can do with it
what you will. But all you get is the object. So:

(Anonymous)
  sub print_it($thingie must toString()) { print $thingie.toString(); }

(Yclept)
  role Stringable {
    must toString();
  }

  sub print_it(Stringable $thingie) { print $thingie.toString(); }

Versus

(Discrete)
  role Stringify {
    must toString();
    method stringify() { return .toString(); }
  }

  sub print_it(Stringify $thingie) { print $thingie.stringify(); }

The former cases don't add any methods to the objects method table, so an
"inferred" object type is okay. The latter requires that a stringify()
method be available, so you'll have to have an object that declared itself
C<does Stringify> at the outset.

=Austin

Reply via email to