ðŸ”¬57. Examining the Real role of Perl 6, part 1

# ðŸ”¬57. Examining the Real role of Raku, part 1

N. B. Perl 6 has been renamed to Raku. Click to read more.

During the last few days, we talked a lot about the Real role. Lets us then look at it more precisely. The code is located in the src/core/Real.pm file.

It contains the role itself and a few subroutines implementing different infixes. TheÂ Real role in its turn implements theÂ Numeric role:

```my role Real does Numeric {
. . .
}```

It is interesting that the class definition also needs some knowledge about theÂ ComplexÂ class, thatâ€™s why there is a forward class declaration in the first line of the file:

`my class Complex { ... }`

TheÂ RealÂ role defines many trigonometrical functions as methods, and as we already saw, they are using theÂ Bridge method:

```method sqrt() { self.Bridge.sqrt }
method rand() { self.Bridge.rand }
method sin() { self.Bridge.sin }
method asin() { self.Bridge.asin }
method cos() { self.Bridge.cos }
method acos() { self.Bridge.acos }
method tan() { self.Bridge.tan }
method atan() { self.Bridge.atan }```

Another set of methods include generic methods that manipulate the value directly:

```method abs() { self < 0 ?? -self !! self }
proto method round(|) {*}
multi method round(Real:D:) {
(self + 1/2).floor; # Rat NYI here, so no .5
}
multi method round(Real:D: Real() \$scale) {
(self / \$scale + 1/2).floor * \$scale;
}
method truncate(Real:D:) {
self == 0 ?? 0 !! self < 0 ?? self.ceiling !! self.floor
}```

Thereâ€™s a really interesting and useful variant of theÂ round method, which allows you to align the number to the grid you need:

```> 11.5.round(3)
12
> 10.1.round(3)
9```

Another set of methods are used to convert a number to different data types:

```method Rat(Real:D: Real \$epsilon = 1.0e-6) { self.Bridge.Rat(\$epsilon) }
method Complex() { Complex.new(self.Num, 0e0) }
multi method Real(Real:D:) { self }
multi method Real(Real:U:) {
self.Mu::Real; # issue a warning;
self.new
}
method Bridge(Real:D:) { self.Num }
method Int(Real:D:) { self.Bridge.Int }
method Num(Real:D:) { self.Bridge.Num }
multi method Str(Real:D:) { self.Bridge.Str }```

And here we have a problem in the matrix. TheÂ Bridge method is defined in such a way that it calls theÂ Num method. In its turn,Â NumÂ is callingÂ Bridge, which callsÂ Num.

Run one of the following lines of code, and Rakudo will hang:

`Real.new.say;`
`Real.new.Str;`