Wait the light to fall

🎄 3/25. 在 Raku 中生成随机整数

焉知非鱼

欢迎来到 Raku One-Liner Advent Calendar 的第3天! 今天,我们将生成随机数。

您可能会问,与它有什么关系,调用一种 rand 函数不是常规任务吗? 好吧,从某种意义上说,是的,但在Raku中,您可能更喜欢调用方法。

我们来看看Raku日历中8月的代码:

2019.rand.Int.say

这就是整个程序! 它只使用方法调用,方法一个接一个地链接在一起。 如果您以前从未见过Raku,那么你首先注意到的是在一个数字上调用的方法。 在Raku中,这一点也不特别。

在数字上调用 rand 方法可能是对 Cool类 中定义的方法的调用,该类立即代理给数字的数字表示:

method rand() { self.Num.rand }

稍后在 Num类 中,会发生对底层 NQP 引擎的调用:

method rand(Num:D: ) {
    nqp::p6box_n(nqp::rand_n(nqp::unbox_n(self)));
}

在我们的示例中,对象 2019Int,因此 rand 被直接分派给 Num 类的方法。

rand 方法返回一个浮点数,因此在其上调用 Int 来获取整数。

运行代码几次以确认它生成随机数:

$ raku -e'2019.rand.Int.say'
543
$ raku -e'2019.rand.Int.say'
1366
$ raku -e'2019.rand.Int.say'
1870

如果您想了解随机数生成器的质量,请深入挖掘 NQP 和 MoarVM,然后再深入了解虚拟机的后端引擎。 要使结果可重复(例如,对于测试),通过调用 srand 函数来设置种子:

$ raku -e'srand(10); 2019.rand.Int.say'
296
$ raku -e'srand(10); 2019.rand.Int.say'
296

请注意,srand 例程是子例程,而不是方法。 它也在同一个 Num 类中定义:

proto sub srand($, *%) {*}
multi sub srand(Int:D $seed --> Int:D) { 
    nqp::p6box_i(nqp::srand($seed))
}

如果你有机会看到源文件,你很可能会注意到 rand 还有一个独立的子例程:

proto sub rand(*%) {*}
multi sub rand(--> Num:D) {
    nqp::p6box_n(nqp::rand_n(1e0))
}

你只能在没有参数的情况下调用它,在这种情况下Raku会生成一个介于0和1之间的随机数。如果你传递参数,你会得到一个错误,说明方法调用更可取:

$ raku -e'rand(20)'
===SORRY!=== Error while compiling -e
Unsupported use of rand(N); in Raku please use N.rand for Num or (^N).pick for Int result
at -e:1
------> rand⏏(20)

好吧,我们从最初的单行开始深度挖掘,所以让我们明天看与另一段令人敬畏的Raku代码!

原文: https://raku.online/2018/12/03/generating-random-integers-in-perl-6/