Examining the Real role of Raku, part 2

今天,我们继续对几天前开始的 Real 角色进行初步探索。

与其方法一起,角色包含许多子例程(放置在角色之外),它们使用 Real 类型的对象定义中缀运算符。名单不长,所以让我把它复制在这里:

multi sub infix:<+>(Real \a, Real \b) { a.Bridge + b.Bridge }
multi sub infix:<->(Real \a, Real \b) { a.Bridge - b.Bridge }
multi sub infix:<*>(Real \a, Real \b) { a.Bridge * b.Bridge }
multi sub infix:</>(Real \a, Real \b) { a.Bridge / b.Bridge }
multi sub infix:<%>(Real \a, Real \b) { a.Bridge % b.Bridge }
multi sub infix:<**>(Real \a, Real \b) { a.Bridge ** b.Bridge }
multi sub infix:«<=>»(Real \a, Real \b) { a.Bridge <=> b.Bridge }
multi sub infix:<==>(Real \a, Real \b) { a.Bridge == b.Bridge }
multi sub infix:«<»(Real \a, Real \b) { a.Bridge < b.Bridge }
multi sub infix:«<=»(Real \a, Real \b) { a.Bridge <= b.Bridge }
multi sub infix:«≤» (Real \a, Real \b) { a.Bridge ≤ b.Bridge }
multi sub infix:«>»(Real \a, Real \b) { a.Bridge > b.Bridge }
multi sub infix:«>=»(Real \a, Real \b) { a.Bridge >= b.Bridge }
multi sub infix:«≥» (Real \a, Real \b) { a.Bridge ≥ b.Bridge }

proto sub infix:<mod>($, $) is pure {*}
multi sub infix:<mod>(Real $a, Real $b) {
    $a - ($a div $b) * $b;
}

如您所见,大多数操作符都使用 Bridge 方法,该方法允许在派生类中使用相同的代码来重新定义该 bridge。

还有一个用于否定的前缀操作:

multi sub prefix:<->(Real:D \a) { -a.Bridge }

cis 函数作为类型转换器返回一个复数:

roto sub cis($) {*}
multi sub cis(Real $a) { $a.cis }

试试看:

> cis(pi)
-1+1.22464679914735e-16i

> cis(pi).WHAT
(Complex)

有点出色,有一个 atan2 函数:

proto sub atan2($, $?) {*}
multi sub atan2(Real \a, Real \b = 1e0) { a.Bridge.atan2(b.Bridge) }
# should really be (Cool, Cool), and then (Cool, Real) and (Real, Cool)
# candidates, but since Int both conforms to Cool and Real, we'd get lots
# of ambiguous dispatches. So just go with (Any, Any) for now.
multi sub atan2( \a, \b = 1e0) { a.Numeric.atan2(b.Numeric) }

这有点奇怪,因为它不遵循其他三角函数的实现方式。 atan2 例程也被定义为一种方法:

proto method atan2(|) {*}
multi method atan2(Real $x = 1e0) { self.Bridge.atan2($x.Bridge) }
multi method atan2(Cool $x = 1e0) { self.Bridge.atan2($x.Numeric.Bridge) }

所有其他的三角函数只作为 Real 方法存在。其余部分在 src/core/Numeric.pm 文件中定义为独立子例程,例如:

proto sub cos($) is pure {*}
multi sub cos(Numeric \x) { x.cos }
multi sub cos(Cool \x) { x.Numeric.cos }

. . .

proto sub atan($) is pure {*}
multi sub atan(Numeric \x) { x.atan }
multi sub atan(Cool \x) { x.Numeric.atan }

还有几个例程,但让我们跳过它们,因为它们非常简单明了。

在接下来的部分中,我们将探讨 Real 角色的两个方法:polymodbase。敬请关注!

Raku 

comments powered by Disqus