Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Metamodel::TypePretense and Metamodel::MethodDelegation #3352

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/Type/Metamodel/CurriedRoleHOW.pod6
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ a single parameter an instantiated role will also be of the same type:
role Zape[::T] {};
say Zape[Int].HOW; #: «Perl6::Metamodel::CurriedRoleHOW.new␤»

Curried roles L<pretend to be|/type/Metamodel::TypePretense> of types
JJ marked this conversation as resolved.
Show resolved Hide resolved
C<Mu>, C<Any>, and C<Cool>, and
L<delegate|/type/Metamodel::MethodDelegation> methods to C<Any>.

I<Note>: As most of the C<Metamodel> classes, this class is here mainly for
illustration purposes and it's not intended for the final user to instantiate.

JJ marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
68 changes: 68 additions & 0 deletions doc/Type/Metamodel/MethodDelegation.pod6
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
=begin pod :kind<Type> :subkind<role> :category<metamodel>

JJ marked this conversation as resolved.
Show resolved Hide resolved
=TITLE role Metamodel::MethodDelegation

=SUBTITLE Metarole for delegating method dispatch

role Metamodel::MethodDelegation { }

I<Warning>: this role is part of the Rakudo implementation, and is not
a part of the language specification.

Methods of C<Any> and C<Mu> can be invoked on roles, despite them not
actually having these types as parents:

=begin code
role Role { }

say Role.raku; # OUTPUT: «Role␤»
say Role.^pun.^parents(:all).map(*.^name); # OUTPUT: «()␤»
=end code

C<Metamodel::MethodDelegation> is the metarole responsible for this
behavior. Using the metamethods this provides, metaobjects can delegate
method dispatch to another type object. This can be useful when
implementing types that shouldn't store methods of their own through
L<C<Metamodel::MethodContainer>|/type/Metamodel::MethodContainer>, but
should still support method dispatch somehow.

All this metarole does is provide an interface for storing a type object
to delegate methods to and provide a default C<find_method> method for
delegating method lookups to that type object if no other method lookup
behavior for it exists; any other behavior related to methods is left up
to the metaclasses that do this metarole to implement themselves.

Because method delegation is a property of the metaclass for a HOW, not
HOWs themselves, the C<delegate_methods_to> and
C<delegating_methods_to> metamethods this metarole provides must be
invoked directly through a metaclass or HOW, not with C<.^> syntax:

=for code :preamble<role Role { }>
say Role.HOW.delegating_methods_to.^name; # OUTPUT: «Any␤»

This metarole is commonly used in combination with
L<C<Metamodel::TypePretense>|/type/Metamodel::TypePretense>.

=head1 Methods

=head2 method delegate_methods_to

method delegate_methods_to($type)

Delegates methods to C<$type>. This should be a type object, but may be
any object with a C<find_method> metamethod technically.

=head2 method delegating_methods_to

method delegating_methods_to()

Returns the type object a metaobject is delegating methods to.

=head2 method find_method

method find_method($obj, $name)

Looks up a method on the type object this metaobject is delegating
method dispatch to.

=end pod
4 changes: 4 additions & 0 deletions doc/Type/Metamodel/ParametricRoleGroupHOW.pod6
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ my \zape := Metamodel::ParametricRoleGroupHOW.new_type( name => "zape");
my \zipi := Metamodel::ParametricRoleHOW.new_type( name => "zipi", group => zape);
say zipi.HOW; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new␤»

Role groups L<pretend to be|/type/Metamodel::TypePretense> of types
C<Mu>, C<Any>, and C<Cool>, and
L<delegate|/type/Metamodel::MethodDelegation> methods to C<Any>.

I<Note>: As most of the C<Metamodel> classes, this class is here mainly for
illustration purposes and it's not intended for the final user to instantiate.

Expand Down
4 changes: 4 additions & 0 deletions doc/Type/Metamodel/ParametricRoleHOW.pod6
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ say zipi.HOW; # OUTPUT: «Perl6::Metamodel::ParametricRoleHOW.new␤»
The extra C<group> argument will need to be used to integrate it in a parametric
role group, which will need to be defined in advance.

Roles L<pretend to be|/type/Metamodel::TypePretense> of types C<Mu>,
C<Any>, and C<Cool>, and L<delegate|/type/Metamodel::MethodDelegation>
methods to C<Any>.

I<Note>: As most of the C<Metamodel> classes, this one is here mainly for
illustration purposes and it's not intended for the final user to instantiate,
unless their intention is really to create a parametric role group.
Expand Down
75 changes: 75 additions & 0 deletions doc/Type/Metamodel/TypePretense.pod6
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
=begin pod :kind<Type> :subkind<role> :category<metamodel>

JJ marked this conversation as resolved.
Show resolved Hide resolved
=TITLE role Metamodel::TypePretense

=SUBTITLE Metarole for type pretenses

role Metamodel::TypePretense { }

I<Warning>: this role is part of the Rakudo implementation, and is not
a part of the language specification.

Any role will type-check as C<Mu>, C<Any>, and C<Cool>, but don't
actually have these classes as parents:

=begin code
class Class { }
role Role { }

say Role ~~ Mu; # OUTPUT: «True␤»
say Role ~~ Any; # OUTPUT: «True␤»
say Role ~~ Cool; # OUTPUT: «True␤»

say Class.^parents(:all).map(*.^name); # OUTPUT: «(Any Mu)␤»
say Role.^pun.^parents(:all).map(*.^name); # OUTPUT: «()␤»
=end code

C<Metamodel::TypePretense> is the metarole that's responsible for this
behavior. Using the metamethods this provides, types can C<pretend to
be> other types, i.e. types can type-check as other types. This can be
useful when implementing types that should not store parent types
through
L<C<Metamodel::MultipleInheritance>|/type/Metamodel::MultipleInheritance>,
but should still type-check like other types somehow.

All this metarole does is provide an interface for storing type objects
in a HOW and provide a default C<type_check> method that allows types to
type-check as the types they're pretending to be if no other
type-checking behavior for it exists; any other behavior related to type
pretenses are left up to the metaclasses that do this metarole to
implement themselves.

Because type pretenses are a property of the metaclass for a HOW, not
HOWs themselves, the C<pretend_to_be> and C<pretending_to_be>
metamethods this metarole provides must be invoked directly through a
metaclass or HOW, not with C<.^> syntax:

=for code :preamble<role Role { }>
say Role.HOW.pretending_to_be.map(*.^name); # OUTPUT: «(Cool Any Mu)»

This metarole is commonly used in combination with
L<C<Metamodel::MethodDelegation>|/type/Metamodel::MethodDelegation>.

=head1 Methods

=head2 method pretend_to_be

method pretend_to_be(@types)

Makes all types for a type of HOW pretend to be any of the type objects
in C<@types>.

=head2 method pretending_to_be

method pretending_to_be()

Returns the type objects this type of HOW is pretending to be.

=head2 method type_check

method type_check($obj, $checkee)

If C<$checkee> is the same object as C<$obj> or is of any of the types
C<$obj> is pretending to be, returns C<1>, otherwise returns C<0>.

=end pod