Rules / Types, classes & roles / metamodel

Metamodel::ClassHOW Reference

Metaobject representing a Raku class.

What it is #

Position in the hierarchy #

Inherits from
Does
Inherited byMetamodel::GrammarHOW

Routines #

Signatures are reproduced from the documentation, including their declared return types. A routine listed here is part of the type's published interface; whether Raku++ implements it is a separate question, answered by the examples below.

method add_fallback #

method add_fallback($obj, $condition, $calculator)

Installs a method fallback, that is, add a way to call methods that weren't statically added. Both $condition and $calculator must be callables that receive the invocant and the method name once a method is called that can't be found in the method cache. If $condition returns a true value, $calculator is called with the same arguments, and must return the code object to be invoked as the method, and is added to the method cache.

method can #

method can($obj, $method-name)

Given a method name, it returns a List of methods that are available with this name. In this example, class B has two possible methods available with name x (though a normal method call would only invoke the one installed in B directly). The one in B has arity 1 (i.e. it expects one argument, the invocant (self)), and the one in A expects 2 arguments (self and $a).

method lookup #

method lookup($obj, $method-name --> Method:D)

Returns Method:D.

Returns the first matching Method with the provided name. If no method was found, returns a VM-specific sentinel value (typically a low-level NULL value) that can be tested for with a test for definedness. It is potentially faster than .^can but does not provide a full list of all candidates.

method compose #

method compose($obj)

A call to compose brings the metaobject and thus the class it represents into a fully functional state, so if you construct or modify a class, you must call the compose method before working with the class. It updates the method cache, checks that all methods that are required by roles are implemented, does the actual role composition work, and sets up the class to work well with language interoperability.

method new_type #

method (:$name, :$repr = 'P6opaque', :$ver, :$auth)

Creates a new type from the metamodel, which we can proceed to build We add a single method by using Higher Order Workings methods, and then we can use that method directly as class method; we can then compose the type, following which we can create already an instance, which will behave in the exact same way.

Examples, run three ways #

Every example below comes from the official documentation, together with the output that documentation asserts. Each was then executed by Rakudo and by Raku++ when this page was built. Where the three agree, one result is shown; where they do not, all three are — because which of them is wrong is exactly the information worth having.

3 all-differ · 1 no-output · 1 ok

class Metamodel::ClassHOW
    does Metamodel::Naming
    does Metamodel::Documenting
    does Metamodel::Versioning
    does Metamodel::Stashing
    does Metamodel::AttributeContainer
    does Metamodel::MethodContainer
    does Metamodel::PrivateMethodContainer
    does Metamodel::MultiMethodContainer
    does Metamodel::RoleContainer
    does Metamodel::MultipleInheritance
    does Metamodel::DefaultParent
    does Metamodel::C3MRO
    does Metamodel::MROBasedMethodDispatch
    does Metamodel::MROBasedTypeChecking
    does Metamodel::Trusting
    does Metamodel::BUILDPLAN
    does Metamodel::Mixins
    does Metamodel::ArrayType
    does Metamodel::BoolificationProtocol
    does Metamodel::REPRComposeProtocol
    does Metamodel::Finalization
        { }

Not executed: the documentation states no expected output for this example.

say so Int.HOW ~~ Metamodel::ClassHOW;    # OUTPUT: «True␤»
say Int.^methods(:all).pick.name;         # OUTPUT: «random Int method name␤»
Documentation
True
random Int method name
Rakudo
True
min
Raku++
True

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

class A      { method x($a) {} };
class B is A { method x()   {} };
say B.^can('x').elems;              # OUTPUT: «2␤»
for B.^can('x') {
    say .arity;                     # OUTPUT: «1, 2␤»
}
Documentation
2
1, 2
Rakudo
2
1
2
Raku++
1
0

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

say Str.^lookup('Int').raku; # OUTPUT: «method Int (Str:D $: *%_) { #`(Method|39910024) ... }␤»

for <uppercase  uc> {
    Str.^lookup: $^meth andthen .("foo").say
        orelse "method `$meth` not found".say
}
# OUTPUT:
# method `uppercase` not found
# FOO
Documentation
method Int (Str:D $: *%_) { #`(Method|39910024) ... }
Rakudo
method Int (Str:D $:: *%_ --> Int:D) { #`(Method|5894990565160) ... }
method `uppercase` not found
FOO
Raku++
&Int

All three differ. Needs a human.

Not yet examined. Which of these is correct has not been established — do not treat either engine as settled here.

my $type = Metamodel::ClassHOW.new_type(name => "NewType",
                                        ver => v0.0.1,
                                        auth => 'github:raku' );
$type.HOW.add_method($type,"hey", method { say "Hey" });
$type.hey;     # OUTPUT: «Hey␤»
$type.HOW.compose($type);
my $instance = $type.new;
$instance.hey; # OUTPUT: «Hey␤»
Output
Hey
Hey

Documentation, Rakudo and Raku++ all agree.