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