class Metamodel::ClassHOW

Metaobject representing a Raku class.

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::InvocationProtocol
    does Metamodel::Finalization
        { }

Warning: this class is part of the Rakudo implementation, and is not a part of the language specification.

Metamodel::ClassHOW is the metaclass behind the class keyword.

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

Methods

method add_fallback

method add_fallback(Metamodel::ClassHOW:D: $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.

If $condition returns a false value, the next fallback (if any) is tried, and if none matches, an exception of type X::Method::NotFound is thrown.

User-facing code (that is, code not dabbling with metaclasses) should use method FALLBACK instead.

method can

method can(Metamodel::ClassHOW:D: $obj$method-name)

Given a method name, it returns a List of methods that are available with this name.

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␤» 
}

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(Metamodel::ClassHOW:D: $obj$method-name --> 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.

say Str.^lookup('Int').perl# OUTPUT: «method Int (Str:D $: *%_) { #`(Method|39910024) ... }␤» 
 
for <upper-case  uc> {
    Str.^lookup: $^meth andthen .("foo").say
        orelse "method `$meth` not found".say
}
# OUTPUT: 
# method `upper-case` not found 
# FOO

method compose

method compose(Metamodel::ClassHOW:D: $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

my $type = Metamodel::ClassHOW.new_type(name => "NewType",
                                        ver => v0.0.1,
                                        auth => 'github:perl6' );
$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␤»

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.

Type Graph

Type relations for Metamodel::ClassHOW
perl6-type-graph Metamodel::ClassHOW Metamodel::ClassHOW Any Any Metamodel::ClassHOW->Any Metamodel::Naming Metamodel::Naming Metamodel::ClassHOW->Metamodel::Naming Metamodel::Documenting Metamodel::Documenting Metamodel::ClassHOW->Metamodel::Documenting Metamodel::Versioning Metamodel::Versioning Metamodel::ClassHOW->Metamodel::Versioning Metamodel::Stashing Metamodel::Stashing Metamodel::ClassHOW->Metamodel::Stashing Metamodel::AttributeContainer Metamodel::AttributeContainer Metamodel::ClassHOW->Metamodel::AttributeContainer Metamodel::Finalization Metamodel::Finalization Metamodel::ClassHOW->Metamodel::Finalization Metamodel::MethodContainer Metamodel::MethodContainer Metamodel::ClassHOW->Metamodel::MethodContainer Metamodel::PrivateMethodContainer Metamodel::PrivateMethodContainer Metamodel::ClassHOW->Metamodel::PrivateMethodContainer Metamodel::MultiMethodContainer Metamodel::MultiMethodContainer Metamodel::ClassHOW->Metamodel::MultiMethodContainer Metamodel::RoleContainer Metamodel::RoleContainer Metamodel::ClassHOW->Metamodel::RoleContainer Metamodel::MultipleInheritance Metamodel::MultipleInheritance Metamodel::ClassHOW->Metamodel::MultipleInheritance Metamodel::DefaultParent Metamodel::DefaultParent Metamodel::ClassHOW->Metamodel::DefaultParent Metamodel::C3MRO Metamodel::C3MRO Metamodel::ClassHOW->Metamodel::C3MRO Metamodel::MROBasedMethodDispatch Metamodel::MROBasedMethodDispatch Metamodel::ClassHOW->Metamodel::MROBasedMethodDispatch Metamodel::MROBasedTypeChecking Metamodel::MROBasedTypeChecking Metamodel::ClassHOW->Metamodel::MROBasedTypeChecking Metamodel::Trusting Metamodel::Trusting Metamodel::ClassHOW->Metamodel::Trusting Metamodel::BUILDPLAN Metamodel::BUILDPLAN Metamodel::ClassHOW->Metamodel::BUILDPLAN Metamodel::Mixins Metamodel::Mixins Metamodel::ClassHOW->Metamodel::Mixins Metamodel::BoolificationProtocol Metamodel::BoolificationProtocol Metamodel::ClassHOW->Metamodel::BoolificationProtocol Mu Mu Any->Mu Metamodel::GrammarHOW Metamodel::GrammarHOW Metamodel::GrammarHOW->Metamodel::ClassHOW Metamodel::GrammarHOW->Metamodel::DefaultParent

Expand above chart

Routines supplied by role Metamodel::Naming

Metamodel::ClassHOW does role Metamodel::Naming, which provides the following routines:

(Metamodel::Naming) method name

method name($type)

Returns the name of the metaobject, if any.

say 42.^name;       # OUTPUT: «Int␤»

(Metamodel::Naming) method set_name

method set_name($type$new_name)

Sets the new name of the metaobject.

Routines supplied by role Metamodel::Documenting

Metamodel::ClassHOW does role Metamodel::Documenting, which provides the following routines:

(Metamodel::Documenting) method set_why

method set_why($why)

Sets the documentation for a type to $why.

(Metamodel::Documenting) method WHY

method WHY()

Returns the documentation for a type.

Routines supplied by role Metamodel::Versioning

Metamodel::ClassHOW does role Metamodel::Versioning, which provides the following routines:

(Metamodel::Versioning) method ver

method ver($obj)

Returns the version of the metaobject, if any, otherwise returns Mu.

(Metamodel::Versioning) method auth

method auth($obj)

Returns the author of the metaobject, if any, otherwise returns an empty string.

(Metamodel::Versioning) method api

method api($obj)

Returns the API of the metaobject, if any, otherwise returns an empty string.

(Metamodel::Versioning) method set_ver

method set_ver($obj$ver)

Sets the version of the metaobject.

(Metamodel::Versioning) method set_auth

method set_auth($obj$auth)

Sets the author of the metaobject.

(Metamodel::Versioning) method set_api

method set_api($obj$api)

Sets the API of the metaobject.

Routines supplied by role Metamodel::Stashing

Metamodel::ClassHOW does role Metamodel::Stashing, which provides the following routines:

(Metamodel::Stashing) method add_stash

method add_stash($type_obj)

Creates and sets a stash for a type, returning $type_obj.

This method is typically called as the last step of creating a new type. For example, this is how it would be used in a minimal HOW that only supports naming and stashing:

class WithStashHOW
    does Metamodel::Naming
    does Metamodel::Stashing
{
    method new_type(WithStashHOW:_: Str:D :$name! --> Mu{
        my WithStashHOW:D $meta := self.new;
        my Mu             $type := Metamodel::Primitives.create_type: $meta'Uninstantiable';
        $meta.set_name: $type$name;
        self.add_stash: $type
    }
}
 
my Mu constant WithStash = WithStashHOW.new_type: :name<WithStash>;
say WithStash.WHO# OUTPUT: «WithStash␤» 

Routines supplied by role Metamodel::AttributeContainer

Metamodel::ClassHOW does role Metamodel::AttributeContainer, which provides the following routines:

(Metamodel::AttributeContainer) method add_attribute

method add_attribute(Metamodel::AttributeContainer: $obj$attribute)

Adds an attribute. $attribute must be an object that supports the methods name, type and package, which are called without arguments. It can for example be of type Attribute.

(Metamodel::AttributeContainer) method attributes

method attributes(Metamodel::AttributeContainer: $obj)

Returns a list of attributes. For most Raku types, these will be objects of type Attribute.

(Metamodel::AttributeContainer) method set_rw

method set_rw(Metamodel::AttributeContainer: $obj)

Marks a type whose attributes default to having a write accessor. For example in

class Point is rw {
    has $.x;
    has $.y;
}

The is rw trait on the class calls the set_rw method on the metaclass, making all the attributes implicitly writable, so that you can write;

my $p = Point.new(x => 1=> 2);
$p.x = 42;

(Metamodel::AttributeContainer) method rw

method rw(Metamodel::AttributeContainer: $obj)

Returns a true value if method set_rw has been called on this object, that is, if new public attributes are writable by default.

Routines supplied by role Metamodel::Finalization

Metamodel::ClassHOW does role Metamodel::Finalization, which provides the following routines:

(Metamodel::Finalization) method setup_finalization

method setup_finalization(Metamodel::Finalization:D: $obj)

Collects the DESTROY submethods from this class and all its superclasses, and marks the class as needing action on garbage collection.

A metamodel for a kind that implements finalization semantics must call this method at type composition time.

(Metamodel::Finalization) method destroyers

method destroyers(Metamodel::Finalization:D: $obj --> List:D)

Returns a list of all finalization methods.

Routines supplied by role Metamodel::MethodContainer

Metamodel::ClassHOW does role Metamodel::MethodContainer, which provides the following routines:

(Metamodel::MethodContainer) method add_method

method add_method(Metamodel::MethodContainer: $obj$name$code)

Adds a method to the metaclass, to be called with name $name. This should only be done before a type is composed.

(Metamodel::MethodContainer) method methods

method methods(Metamodel::MethodContainer: $obj:$all:$local)

Returns a list of public methods available on the class (which includes methods from superclasses and roles). By default this stops at the classes Cool, Any or Mu; to really get all methods, use the :all adverb. If :local is set, only methods declared directly in the class are returned.

class A {
    method x() { };
}
 
say A.^methods();                   # x 
say A.^methods(:all);               # x infinite defined ...

The returned list contains objects of type Method, which you can use to introspect their signatures and call them.

Some introspection method-look-alikes like WHAT will not show up, although they are present in any Raku object. They are handled at the grammar level and will likely remain so for bootstrap reasons.

(Metamodel::MethodContainer) method method_table

method method_table(Metamodel::MethodContainer:D: $obj --> Hash:D)

Returns a hash where the keys are method names, and the values are methods. Note that the keys are the names by which the methods can be called, not necessarily the names by which the methods know themselves.

(Metamodel::MethodContainer) method lookup

method lookup(Metamodel::MethodContainer: $obj$name --> Method)

Returns the first matching method object of the provided $name or (Mu) if no method object was found. The search for a matching method object is done by following the mro of $obj. Note that lookup is supposed to be used for introspection, if you're after something which can be invoked you probably want to use find_method instead.

say 2.5.^lookup("sqrt").perl:      # OUTPUT: «method sqrt (Rat $: *%_) ...␤» 
say Str.^lookup("BUILD").perl;     # OUTPUT: «submethod BUILD (Str $: :$value = "", *%_ --> Nil) ...␤» 
say Int.^lookup("does-not-exist"); # OUTPUT: «(Mu)␤»

The difference between find_method and lookup are that find_method will use a default candidate for parametric roles, whereas lookup throws an exception in this case, and that find_method honors FALLBACK methods, which lookup does not.

Routines supplied by role Metamodel::PrivateMethodContainer

Metamodel::ClassHOW does role Metamodel::PrivateMethodContainer, which provides the following routines:

(Metamodel::PrivateMethodContainer) method add_private_method

method add_private_method(Metamodel::PrivateMethodContainer: $obj$name$code)

Adds a private method $code with name $name.

(Metamodel::PrivateMethodContainer) method private_method_table

method private_method_table(Metamodel::PrivateMethodContainer: $obj)

Returns a hash of name => &method_object

Routines supplied by role Metamodel::RoleContainer

Metamodel::ClassHOW does role Metamodel::RoleContainer, which provides the following routines:

(Metamodel::RoleContainer) method add_role

method add_role(Metamodel::RoleContainer:D: $objMu $role)

Adds the $role to the list of roles to be composed.

(Metamodel::RoleContainer) method roles_to_compose

method roles_to_compose(Metamodel::RoleContainer:D: $obj --> List:D)

returns a list of roles added with add_role, which are to be composed at type composition time.

Routines supplied by role Metamodel::MultipleInheritance

Metamodel::ClassHOW does role Metamodel::MultipleInheritance, which provides the following routines:

(Metamodel::MultipleInheritance) method add_parent

method add_parent(Metamodel::MultipleInheritance:D: $Obj$parent:$hides)

Adds $parent as a parent type. If $hides is set to a true value, the parent type is added as a hidden parent.

$parent must be a fully composed typed. Otherwise an exception of type X::Inheritance::NotComposed is thrown.

(Metamodel::MultipleInheritance) method parents

method parents(Metamodel::MultipleInheritance:D: $obj:$all:$tree)

Returns the list of parent classes. By default it stops at Cool, Any or Mu, which you can suppress by supplying the :all adverb. With :tree, a nested list is returned.

class D { };
class C1 is D { };
class C2 is D { };
class B is C1 is C2 { };
class A is B { };
 
say A.^parents(:all).perl;
# OUTPUT: «(B, C1, C2, D, Any, Mu)␤» 
say A.^parents(:all:tree).perl;
# OUTPUT: «[B, ([C1, [D, [Any, [Mu]]]], [C2, [D, [Any, [Mu]]]])]␤»

(Metamodel::MultipleInheritance) method hides

method hides(Metamodel::MultipleInheritance:D: $obj)

Returns a list of all hidden parent classes.

(Metamodel::MultipleInheritance) method hidden

method hidden(Metamodel::MultipleInheritance:D: $obj)

Returns a true value if (and only if) the class is marked with the trait is hidden.

(Metamodel::MultipleInheritance) method set_hidden

method set_hidden(Metamodel::MultipleInheritance:D: $obj)

Marks the type as hidden.

Routines supplied by role Metamodel::C3MRO

Metamodel::ClassHOW does role Metamodel::C3MRO, which provides the following routines:

(Metamodel::C3MRO) method compute_mro

method compute_mro($type)

Computes the method resolution order.

(Metamodel::C3MRO) method mro

method mro($type)

Returns a list of types in the method resolution order, even those that are marked is hidden.

say Int.^mro;   # OUTPUT: «((Int) (Cool) (Any) (Mu))␤»

(Metamodel::C3MRO) method mro_unhidden

method mro_unhidden($type)

Returns a list of types in method resolution order, excluding those that are marked with is hidden.

Routines supplied by role Metamodel::MROBasedMethodDispatch

Metamodel::ClassHOW does role Metamodel::MROBasedMethodDispatch, which provides the following routines:

(Metamodel::MROBasedMethodDispatch) method find_method

method find_method($obj$name$no_fallback*%adverbs)

Given a method name, it returns the method object of that name which is closest in the method resolution order (MRO). If no method can be found, it returns a VM-specific sentinel value (typically a low-level NULL value) that can be tested for with a test for definedness:

for <upper-case  uc> {
    Str.^find_method: $^meth andthen .("foo").say
        orelse "method `$meth` not found".say
}
# OUTPUT: 
# method `upper-case` not found 
# FOO

If :no_fallback is supplied, fallback methods are not considered.

(Metamodel::MROBasedMethodDispatch) method find_method_qualified

method find_method_qualified($obj$type$name)

Given a method name and a type, returns the method from that type. This is used in calls like

self.SomeParentClass::the_method();

(Metamodel::MROBasedMethodDispatch) method can

method can($obj$name)

Returns the list of methods of that name the object can do.

(Metamodel::MROBasedMethodDispatch) method publish_method_cache

Defined as:

method publish_method_cache($obj)

Walk MRO and add methods to cache, unless another method lower in the class hierarchy "shadowed" it.

Routines supplied by role Metamodel::Trusting

Metamodel::ClassHOW does role Metamodel::Trusting, which provides the following routines:

(Metamodel::Trusting) method add_trustee

method add_trustee(Metamodel::Trusting:D: $typeMu $trustee)

Trust $trustee.

class A {
    BEGIN A.^add_trustee(B);
    # same as 'trusts B'; 
}

(Metamodel::Trusting) method trusts

method trusts(Metamodel::Trusting:D: $type --> List)

Returns a list of types that the invocant trusts.

class A { trusts Int};
say .^name for A.^trusts;       # Int

(Metamodel::Trusting) method is_trusted

method is_trusted(Metamodel::Trusting:D: $type$claimant)

Returns 1 if $type trusts $claimant, and 0 otherwise. Types always trust themselves.

Routines supplied by role Metamodel::Mixins

Metamodel::ClassHOW does role Metamodel::Mixins, which provides the following routines:

(Metamodel::Mixins) method set_is_mixin

method set_is_mixin($obj)

Marks $obj as being a mixin.

(Metamodel::Mixins) method is_mixin

method is_mixin($obj)

Returns 1 If $obj has been marked as being a mixin with set_is_mixin, otherwise returns 0.

(Metamodel::Mixins) method set_mixin_attribute

method set_mixin_attribute($obj$attr)

Sets the mixin attribute for $obj to $attr (which should be an Attribute instance).

(Metamodel::Mixins) method mixin_attribute

method mixin_attribute($obj)

Returns the mixin attribute for $obj set with set_mixin_attribute.

(Metamodel::Mixins) method setup_mixin_cache

method setup_mixin_cache($obj)

Sets up caching of mixins for $obj. After this metamethod has been called, calls to mixin will not create a new type for mixins of $obj given the same list of roles more than once. This should be called at some point before composition.

(Metamodel::Mixins) method flush_cache

method flush_cache($obj)

No-op.

(Metamodel::Mixins) method generate_mixin

method generate_mixin($obj@roles)

Creates a new mixin metaobject that inherits from $obj and does each of the roles in @roles. This is then composed and has its mixin attribute set (if any exists) before getting returned.

While this generates a new mixin type, this doesn't actually mix it into $obj; if that is what you intend to do, use the mixin metamethod instead.

(Metamodel::Mixins) method mixin

method mixin($obj*@roles:$needs-mixin-attribute)

Generates a new mixin type by calling generate_mixin with $obj and @roles. If $obj is composed, the mixin cache of $obj will be checked for any existing mixin for these beforehand. If $obj is an instance of a type, this will return $obj reblessed with the mixin generated, otherwise this will return the mixin itself.

If $needs-mixin-attribute is True, this will throw an exception if no mixin attribute exists on the mixin generated before returning.