在过去的几天里,我们谈了很多关于 Real
这个角色。让我们更仔细地看看它。该代码位于 src/core/Real.pm
文件中。
它包含角色本身和一些实现不同中缀的子例程。Real
角色又实现了 Numeric
角色:
my role Real does Numeric {
. . .
}
有趣的是,类定义还需要关于 Complex
类的一些知识,这就是为什么在文件的第一行有一个前向类声明:
my class Complex { ... }
Real
角色将许多三角函数定义为方法,正如我们已经看到的,他们正在使用 Bridge 方法:
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 }
另一组方法包括直接操纵值的泛型方法:
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
}
round
方法有一个非常有趣且有用的变体,它允许您将数字与您需要的网格对齐:
> 11.5.round(3)
12
> 10.1.round(3)
9
另一组方法用于将数字转换为不同的数据类型:
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 }
这里我们在矩阵中有一个问题。 Bridge
方法以调用 Num
方法这样的方式被定义。反过来,Num
调用 Bridge
, 而 Bridge 调用 Num
。
运行以下代码行之一,Rakudo 将挂起:
Real.new.say;
Real.new.Str;