Normally in Perl 6, only roles are allowed to be parametric. Here, we\'ll be attempting to make classes, a kind (referred to from here on out as a metaobject) that isn\'t no
Making classes parametric takes a little bit of metaprogramming to accomplish. A simple parametric container class can be implemented like so:
use v6.d;
class Container {
my role ContainerImpl[::T] {
has T $.value;
method new(Container: T $value) {
self.bless: :$value
}
multi method gist(Container:D: --> Str:D) {
$!value.gist
}
multi method Str (Container:D: --> Str:D) {
$!value.Str
}
multi method perl(Container:D: --> Str:D) {
self.^name ~ '.new(' ~ $!value.perl ~ ')'
}
}
method ^parameterize(Mu:U \this, Mu \T) {
my $type := this.^mixin: ContainerImpl[T];
$type.^set_name: this.^name ~ '[' ~ T.^name ~ ']';
$type
}
}
say Container[Int].new(1).perl;
# OUTPUT: Container[Int].new(1)
So how does this work?
Metaclasses that do the Perl6::Metamodel::MetaMethodContainer role, such as Perl6::Metamodel::ClassHOW, can have additional metamethods mixed in with the type's knowhow (which describes how a specific kind of type, such as a class or role, behaves). Rakudo's grammar invokes the parameterize metamethod on any given type with the parametric type and any parameterized types as arguments when parsing a type's name. Normally, types that are parametric are supposed to implement the parametric archetype, but this doesn't get checked here, which allows any type to be parameterized as long as it implements a parameterize metamethod.
The mixin metamethod is specific to the Perl6::Metamodel::Mixins role, which Perl6::Metamodel::ClassHOW also does. The method mixes in a role by reblessing the class so it's considered to be the same type as the (parameterized in this case) role passed to it.
Combining the parameterize and mixin metamethods allows you to implement parametric behaviour in a role, then use it in a class by parameterizing it before mixing it in. This allows the class to behave as if it actually were a parametric type, even though it's still technically not one.