Random thoughts about randomness in Scala
When you need a pseudorandom number in a Java project, what do you use? Many Java programmers would probably just use Math.random()
. Which is just fine if what you need is precisely a pseudorandom floating point number that’s at least 0.0 and but less than 1.0.
Most of the time, though, at least in my experience, what’s needed is a pseudorandom integer. Like, for example, a pseudorandom integer from 1 to 10. We might write
int number = (int) (10 * Math.random()) + 1;
This is error-prone. I’m speaking from personal experience. Like, one time, I misplaced the parentheses and the “random” number was always 1. Or it was always 10. Or something like that. I almost needed to use the debugger, which I’d rather not.
There has to be a better way to get pseudorandom integers without having to worry about screwing up the formula. Just being able to specify you want a number that’s at least 0 but less than a given positive number would be a huge improvement.
There is such a way. Looking at the source of Math.random()
, I learned that the first call to that function in a given session of the Java Virtual Machine causes a new instance of java.util.Random
to come into being.
Each call to Math.random()
causes a call to the Random
instance’s nextDouble()
function. But Random
has a lot of other functions besides nextDouble()
, like nextInt()
, which can give any 32-bit signed integer or it can give a bounded nonnegative number, such as, for example, an integer between 0 and 127 (this example would use a bound
parameter of 128).
And Java 17 added an overload of nextInt()
that also takes an origin
parameter. With that function, you can specify, for example, that you want a pseudorandom number between −72 and 72, instead of having to ask for a number between 0 and 144 and then having to subtract 72.
Whatever’s available in a Java project on a given system should also be available to a Scala project on that same system. So we should be able to import java.util.Random
, instantiate it and use it.
But Scala provides a yet better way, with the class scala.util.Random
and its companion object. The companion object gives the convenience of not having to instantiate a new Random
object each time you need a pseudorandom number.
You still need to put in an import forscala.util.Random
, if you don’t have a wildcard import for scala.util._
(which I don’t recommend just as I don’t recommend importing java.util.*
).
Scala also provides the alphanumeric()
function, which is very nice when you need a String
of pseudorandom alphanumeric ASCII characters, even though it can be a little cumbersome to use. For example,
val alphaNum = Random.alphanumeric
new String(alphaNum.take(8).toArray)
might give you “W1vcC1Hx”. Still, it’s better than writing your own function from scratch.
If you’ve got a better way to use alphanumeric()
to get a String
of a specific length, please post it in the comments.