Examining the Real role of Raku, part 1

在过去的几天里,我们谈了很多关于 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;
Raku 

comments powered by Disqus