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.