Ovid wrote:
My apologies if these have been answered.  I've been chatting with
Jonathan Worthington about some of this and any misconceptions are
mine, not his.

In reading through S12, I see that .can() returns an iterator for the
methods matched.  What I'm curious about is this:

  if $obj.can('fribble') {
    my BadPoet $jibbet = $obj.fribble('repeatedly');

Just because $obj.can('fribble') does not mean that the available
fribble(s) will accept a string argument or return BadPoet instances.
In chatting with Jonathan about this, he speculated that I would have
to manually walk the method objects in the iterator to find out if I
really have a suitable method.  This seems like what we really have is
$object.might($method).  Is there a simpler way of determining if
there's an appropriate method for what I need?  It seems like what we
really want is a method object where I can declare a signature and then
do this:

  if $obj.can($object_with_signature){ ... }

I suppose.  Still, an easier solution might be to allow an optional
second parameter for .can that takes a signature object:

 if $obj.can('fribble', :(string -> BadPoet)) {
   my BadPoet $jibbet = $obj.fribble('repeatedly');

Or you could allow signatures to be attached to strings:

 # pseudo-code:
 if $obj.can('fribble':(string -> BadPoet)) {
   my BadPoet $jibbet = $obj.fribble('repeatedly');

In effect, the signature gets attached as a property of the string,
and 'can()' checks for the signature property.

The only problem that I have with this idea is that I can't think of
any uses for a "signatory string" outside of '.can()'.

This raises my second question.  What if I have this?

  class MadHatter is BadPoet { ... }

If I get back a MadHatter instead of a BadPoet, but I really want the
superclass and not a subclass, how can I enforce that?  Do I have to do
something like this?  (pseudo-code)

What are you looking for that .is() doesn't provide?  The only thing I
can think of is that you're trying to insist that $obj's
implementation be BadPoet - not "BadPoet or a class derived from it",
but "BadPoet".  This strikes me as getting into the same territory as
finalized classes.

  subset ReallyABadPoet where { $^N.type eq "BadPoet" }
  my ReallyABadPoet = $obj.fribble('repeatedly');

I'll assume that you meant to include a variable name on the second line:

 subset ReallyABadPoet where { $^N.type eq "BadPoet" }
 my ReallyABadPoet $obj2 = $obj.fribble('repeatedly');

If so, I fail to see what you gain from this, as opposed to:

 my BadPoet $obj2 = $obj.fribble('repeatedly');

In this case, $obj2 won't accept the product of
$obj.fribble('repeatedly') unless that product ".does('BadPoet')".

That seems to fail because the you'd have to invoke every method to
guarantee that you're really getting back the exact type you want.

As I understand it, Perl 6's typing system does not do "duck typing" -
that is, it uses ".does()" as its primary means of type-checking, not
".can()".  As such, you can check an object's type directly without
having to examine its set of methods - just scan the set of roles that
the object composes until you find the role that you're looking for.

Or am I misunderstanding you?

As such, it seems like we'd need return values to guarantee that the
returned type is exactly what we claimed.

  method foo(Int $bar, Int $baz) returns Int {
    return $foo/$baz;

Since the return value might be a Float, does it get cast to an Int,
thereby discarding information?

As I understand it, yes; a Float would be cast into an Int in this
case.  Though my understanding is that this says more about Ints and
Nums than it does about objects in general.

Jonathan "Dataweaver" Lang

Reply via email to