SE-0202: Random Unification

There is a lot to cover here (the pre-proposal discussion thread has well over 200 posts!)

First, the text of the proposal itself could use a little work. One example is where the main protocol RandomNumberGenerator is described:

It is not clear whether conforming types are intended to be able to provide their own implementations for the two next<T>() methods described in the extension. As written, they are *not* able to, but the comments seem to imply that they should be.

• • •

One major decision in the proposal is to make the default random number generator cryptographically secure. I think we should explore the possibility of providing both a secure generator and a fast generator in the standard library.

• • •

It is not immediately clear how non-uniform distributions fit with the proposal. The normal distribution in particular is used quite frequently, and I would hope that a gaussian generator could be a “drop-in replacement”, at least for floating-point value.

In fact, we should consider including in the standard library some way to generate normally-distributed values, with the ability to specify a generator (eg. “fast” or “secure”) as well as a mean and standard deviation (with default values).

• • •

The proposed syntax for generating a random integer or float less than some upper bound is rather verbose:

Int.random(in: 0..<n)
Double.random(in: 0..<x)

I would like to see a free function along the lines of:

func random<T: FixedWidthInteger>(_ upperBound: T) -> T
  where: /*insert constraints here*/
{
  return T.random(in: 0..<upperBound)
}

And the same thing for BinaryFloatingPoint, so that you can write, eg:

random(n)

and have it do the correct thing. Note that I am *not* asking for the zero-argument version which leads people into the modulo-bias morass, nor for a type-converting version. This function takes one argument (and perhaps an optional generator) and returns a value of the same type as its argument.

Similarly, a free function that takes a range would be nice, and might even supplant the random(n) version entirely:

random(0...15)

My main point here is that repeating type information is unnecessary, inelegant, and non-Swifty. Putting the base implementation in static functions is great for encapsulation, and I support that decision. However, the lack of a free function makes use-sites needlessly verbose.

Having a free function with a simple, well-known name makes it easy to reach for the right tool. And if we introduce a protocol (eg. Randomizable) for types with static func random(…), then that free function could be a single simple trampoline.

7 Likes