ðŸ¦‹17. Parameterised roles in Perl 6

Today, a small excursus into the syntax. Did you know that roles in Perl 6 can have a parameter that makes them similar to generic templates in, say, C++? Hereâ€™s a small example:

```role R {
has \$.value;

\$.value + \$b.value
}

method div(\$b) {
\$.value / \$b.value
}
}```

The R role defines an interface that has a value and two methods for arithmetical operations: add and div.

Now, create a class using the role, initialise two variables and use the methods to get the results:

```class C does R {}

my C \$x = C.new(value => 10);
my C \$y = C.new(value => 3);

say \$x.div(\$y); # 3.333333```

Although the values here were integers, Perl did a good job and returned a rational number for the division. You can easily see it by calling theÂ WHAT method:

```say \$x.add(\$y).WHAT; # (Int)
say \$x.div(\$y).WHAT; # (Rat)```

If you have two integers, the result of their division is always of the Rat type. The actual operator, which is triggered in this case, is the one from src/core/Rat.pm:

```multi sub infix:</>(Int \a, Int \b) {
Â  Â  DIVIDE_NUMBERS a, b, a, b
}```

The DIVIDE_NUMBERS sub returns a Rat value.

Defining a role

How to modify theÂ C class so that it performs integer division? One of the options is to use a parameterised role:

```role R[::T] {
has T \$.value;

T.new(\$.value + \$b.value)
}

method div(\$b) {
T.new(\$.value / \$b.value)
}
}```

TheÂ parameter in square brackets after the role name restricts both the type of theÂ \$.value attribute and the return type of the methods, which return a new object of the typeÂ T. Here, in the template of the role,Â T is just a name, which should later be specified when the role is used.

Using the role

So, letâ€™s make it integer:

`class N does R[Int] {}`

Now the parts of the role that employ theÂ T name replace it with Int, so the class is equivalent to the following definition:

```class C {
has Int \$.value;

Int.new(\$.value + \$b.value)
}

method div(\$b) {
Int.new(\$.value / \$b.value)
}
}```

The new class operates with integers, and the result of the division is an exact 3:

```class N does R[Int] {}

my N \$i = N.new(value => 10);
my N \$j = N.new(value => 3);

say \$i.div(\$j); # 3```

It is also possible to force floating-point values by instructing the role accordingly:

```class F does R[Num] {}

my F \$x = F.new(value => 10e0);
my F \$y = F.new(value => 3e0);

```say \$x.add(\$y).WHAT; # (Num)