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-okunderstand roles or mustdoes-okbe 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