Perl6 中的类型强制

Type coercion in Perl6

如果我有一个 Str 类型的对象,并且我想将它强制转换为一个 Int,据我所知,我可以通过调用 Str 对象上的 Int 方法来做到这一点,如下所示:

"100".Int

我(认为我)知道我可以做到这一点,因为 https://docs.perl6.org/type/Str 的 Str 类型文档列出了 Int 方法。现在,为了将这个新创建的 Int 强制转换为 Complex 类型的对象,我尝试了以下强制操作:

"100".Int.Complex

有效 :-) 所以没问题。除了我无法弄清楚它为什么起作用。 https://docs.perl6.org/type/Int 处的 Int 类型文档未列出 Complex 方法。我确实为 class ComplexStr 找到了一个具有此名称的方法,但我不知道这是否与我的 Int 相关。

那么问题来了:上面的强制转换是怎么实现的呢? Complex 方法从何而来?在尝试之前我怎么知道我实际上可以在 Int 对象上调用它?

(这与其说是答案,不如说是扩展评论。我只知道 Perl 5。)

来自https://docs.perl6.org/type/Cool

Methods in Cool coerce the invocant to a more specific type, and then call the same method on that type. For example both Int and Str inherit from Cool, and calling method substr on an Int converts the integer to Str first.

123.substr(1, 1);   # '2', same as 123.Str.substr(1, 1)

所以看起来123.substr(1, 1)就像更传统的表示法中的Cool(123).substr(1, 1),然后重写为Str(123).substr(1, 1),因为Str继承自Cool (就像向后完成的经典 OOP 一样)。

以类似的方式,似乎 "100".Int.Complex 就像 Cool("100").Int.Complex -> Int("100").Complex -> 100.Complex -> Cool(100).Complex -> Complex(100)

这只是文档不完整的情况。

您总是可以通过调用 .^methods 来了解一个对象支持哪些方法:

perl6 -e '$_>>.name.join(", ").say for 123.^methods.sort(*.name).rotor(5 => 0, :partial)'
ACCEPTS, Bool, Bridge, Capture, Complex
DUMP, FatRat, Int, Num, Numeric
Range, Rat, Real, Str, WHICH
abs, acos, acosec, acosech, acosh
acotan, acotanh, asec, asech, asin
asinh, atan, atan2, atanh, base
ceiling, chr, cis, conj, cos
cosec, cosech, cosh, cotan, cotanh
exp, expmod, floor, gist, is-prime
isNaN, log, log10, lsb, msb
narrow, new, perl, polymod, pred
rand, roots, round, sec, sech
sign, sin, sinh, sqrt, succ

与此同时,我pushed a commit to the docs repo that adds the missing method. The website is already regenerated with the change: https://docs.perl6.org/type/Int#(Real)_method_Complex