A long long time ago… Well, maybe not that long ago… I was a Bachelor student at EPFL in Martin Odersky’s Advanced Programming class (which was really just another name for Functional Programming) learning about Scala.

We had an amazing Teaching Assistant during the exercise sessions who used to give us small extra problems to solve. One day, during the exercise session on Streams, he gave us the following task:

Can you write a function which generates a random string of length n in any given alphabet?

I remember coming up with various implementations which were pretty inelegant. I had completely forgotten about this question until last week, when I needed to implement an alphanumeric strings generator for email validation purposes in a Play! application. I fiddled around with the implementation and finally came up with:

Pretty slick, uh? Let’s walk through it…

Similarly to a List, a Stream has a head and a tail. However, unlike List values, Stream values are computed only when they are needed, i.e. the tail part of a Stream is never evaluated. This makes Streams very attractive to define infinite sequences. One way to define such a sequence is to use Stream.continually, whose signature is def continually[A](elem: => A): Stream[A].

In order to properly understand the difference, let’s run the following in the Scala REPL:

You will of course be presented with a java.lang.StackOverflowError. This is because lists evaluate the tail part. However, if you replace List[A] by Stream[A] and use Stream.cons instead of ::, you won’t have the same problem.

Back to the random generator, we build ourselves and infinite random sequence of integers in the range [0, aphabet.size – 1] with Stream.continually(random.nextInt(alphabet.size)).

Next, we want to convert this to an infinite random sequence of characters in the alphabet by mapping it to said alphabet, i.e. defining a mapping f: Int => Char. We could have done this as follows:

However, that becomes quite verbose, so instead we simply require a String containing the alphabet and we use an implicit conversion defined in the Scala library that lifts Strings to WrappedStrings, which then allows them to be used as IndexedSeq[Char]. Since an IndexSeq[A] has an apply(idx: Int): A method, we can use the String itself as a mapping.

The only thing left is to cut the Stream at the appropriate length (take(n)) and convert it to a String (mkString). Et voilà!

You can of course reuse the same approach to generate random strings over any alphabet:

Oh, and just to be on the safe side, if your application requires secure random strings, you should make sure to get a secure random generator as follows:

Happy coding!