🎄 3/25. Generating random integers in Perl 6

Welcome to Day 3 of the Perl 6 One-Liner Advent Calendar! Today, we will generate random numbers.

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 in Perl 6, you might prefer calling a method

Let’s look at the code for August in the Perl 6 calendar:

2019.rand.Int.say

That’s the whole program, and it generates random numbers below 2019! It only uses method calls, chained one after another. If you have never seen Perl 6 before, the first thing you notice here is a method called on a number. In Perl 6 that’s not something extraordinary.

Calling the rand method on a number potentially is 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 2019 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 Int on it to get an integer.

Run the code a few times to confirm that it generates random numbers:

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

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 the srand function:

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

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. Would you pass the argument, you’ll get an error explaining that a method call is preferable:

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

OK, we dived quite deep from the initial one-liner, so let’s meet tomorrow with another piece of awesome Perl 6 code!

One thought on “🎄 3/25. Generating random integers in Perl 6

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s