Raku Books / Raku One-Liners / Working with Numbers
Generating random integers
You may ask, what’s the deal with it, isn’t it a routine task to call
a kind of a rand function? Well, in some sense, yes, but
you might prefer calling a
method.
Let’s look at the following code:
2020.rand.Int.say;That’s the whole program, and it generates random numbers below 2020. It only uses method calls, chained one after another. If you have never seen Raku before, the first thing you notice here is a method called on a number. That’s not something extraordinary in this language.
Calling the rand method on a number is potentially a
call of the method defined in the Cool class, which is
immediately delegated to a numeric representation of the number:
method rand() { self.Num.rand }Later in the Num class, a call to the underlying NQP
engine happens:
method rand(Num:D: ) {
nqp::p6box_n(nqp::rand_n(nqp::unbox_n(self)));
}In our example, the object 2020 is an Int,
so rand is dispatched directly to the method of the
Num class.
The rand method returns a floating-point number, so call
another method Int on it to get an integer.
Run the code a few times to confirm that it generates random numbers:
$ raku -e'2020.rand.Int.say'
$ raku -e'2020.rand.Int.say'
$ raku -e'2020.rand.Int.say'If you want to understand the quality of the random number generator,
dig deeper to NQP and MoarVM, and later to the backend engine of the
virtual machine. To make the results repeatable (e. g., for tests), set
the seed by calling srand:
$ raku -e'srand(10); 2020.rand.Int.say'
$ raku -e'srand(10); 2020.rand.Int.say'Notice that the srand routine is a subroutine, not a
method. It is also defined in the same Num class:
proto sub srand($, *%) {*}
multi sub srand(Int:D $seed --> Int:D) {
nqp::p6box_i(nqp::srand($seed))
}And if you have the chance to see the source file, you would most
likely notice that there’s also a standalone subroutine for
rand:
proto sub rand(*%) {*}
multi sub rand(--> Num:D) {
nqp::p6box_n(nqp::rand_n(1e0))
}You can only call it without arguments, in which case Perl 6 generates a random number between 0 and 1. If you pass the argument, you get an error explaining that a method call is preferable:
$ 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
⏏(20)
------> randCourse navigation
← Grepping multiples of 3 and 5 | Working with big numbers →