Using the Perl6 Test
module to test an object's type with Buf
:
use Test;
isa-ok Buf.new, Buf;
isa-ok Buf.new, Blob;
isa-ok Buf.new, 'Buf';
isa-ok Buf.new, 'Blob';
ok Buf.new ~~ Buf;
ok Buf.new ~~ Blob;
does-ok Buf.new, Buf;
does-ok Buf.new, Blob;
Here's the output:
not ok 1 - The object is-a 'Buf'
# Failed test 'The object is-a 'Buf''
# at buftest line 3
# Actual type: Buf
not ok 2 - The object is-a 'Blob'
# Failed test 'The object is-a 'Blob''
# at buftest line 5
# Actual type: Buf
ok 3 - The object is-a '"Buf"'
not ok 4 - The object is-a '"Blob"'
# Failed test 'The object is-a '"Blob"''
# at buftest line 9
# Actual type: Buf
ok 5 -
ok 6 -
ok 7 - The object does role 'Buf'
ok 8 - The object does role 'Blob'
How does isa-ok
really work? How does that differ from just ~~
?
What is the difference between testing an object against Buf
vs. 'Buf'
?
Why isn't a Buf
considered to be isa
a Buf
or Blob
? (while it isa
a 'Buf'
but still not a 'Blob'
?
In general, does isa-ok
understand roles or must does-ok
be used for them?
See isa-ok
does not work with parametrized types. (I think the issue title is misleading because aiui it's really about classes vs roles not parameterized vs unparamaterized types. One can write Array[Int]
after all and that's arguably a parameterized type.)
I found this by searching the Rakudo Github repo for 'isa-ok' and clicking on Issues
.
Mu.pm6 defines isa
:
proto method isa(|) {*}
multi method isa(Mu \SELF: Mu $type --> Bool:D) {
nqp::hllbool(SELF.^isa($type.WHAT))
}
multi method isa(Mu \SELF: Str:D $name --> Bool:D) {
return True if .^name eq $name for SELF.^mro;
False
}
The first multi only works if the type is a class. In P6 the word "isa" has a technical meaning that A isa B
iff both A
and B
are classes and A
is, or inherits from, B
.
(More concretely, the isa
of a class that does Perl6::Metamodel::MROBasedTypeChecking
resolves to a method in the corresponding role
that checks for a match based on going through the class's method resolution order.)
A type like Buf
is a role. (Roles can be easily "punned" into corresponding anonymous classes/instances by, eg. Buf.new
, but that doesn't stop Buf
itself being a role.)
A type like Array
works because Array
is a class.
So:
put Array.HOW.^name; # Perl6::Metamodel::ClassHOW+{<anon>}
say Array.^mro; # ((Array) (List) (Cool) (Any) (Mu))
isa-ok Array, List; # ok
put Buf.HOW.^name; # Perl6::Metamodel::ParametricRoleGroupHOW
say Buf.^mro; # No such method 'mro' for invocant of type
# 'Perl6::Metamodel::ParametricRoleGroupHOW'
The string version of isa-ok
applies only if you pass a string version of the type's name. For good or ill it allows for a sloppier way of thinking about types and will accept an exact match.
~~
is "smart matching". It's up to the type on the right to decide if the thing on the left is to be considered a match.
In general, does
isa-ok
understand roles or mustdoes-ok
be used for them?
No it doesn't. You should use does-ok
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With