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