[swift-evolution] [Proposal] Random Unification

Greg Parker gparker at apple.com
Wed Oct 4 20:49:29 CDT 2017

> On Oct 3, 2017, at 11:44 PM, Jonathan Hull via swift-evolution <swift-evolution at swift.org> wrote:
> I like the idea of splitting it into 2 separate “Random” proposals.
> The first would have Xiaodi’s built-in CSPRNG which only has the interface:
> On FixedWidthInteger:
> 	static func random()throws -> Self
> 	static func random(in range: ClosedRange<Self>)throws -> Self
> On Double:
> 	static func random()throws -> Double
> 	static func random(in range: ClosedRange<Double>)throws -> Double
> (Everything else we want, like shuffled(), could be built in later proposals by calling those functions)
> The other option would be to remove the ‘throws’ from the above functions (perhaps fatalError-ing), and provide an additional function which can be used to check that there is enough entropy (so as to avoid the crash or fall back to a worse source when the CSPRNG is unavailable).


> Then a second proposal would bring in the concept of RandomSources (whatever we call them), which can return however many random bytes you ask for… and a protocol for types which know how to initialize themselves from those bytes.  That might be spelled like 'static func random(using: RandomSource)->Self'.  As a convenience, the source would also be able to create FixedWidthIntegers and Doubles (both with and without a range), and would also have the coinFlip() and oneIn(UInt)->Bool functions. Most types should be able to build themselves off of that.  There would be a default source which is built from the first protocol.
> I also really think we should have a concept of Repeatably-Random as a subprotocol for the second proposal.  I see far too many shipping apps which have bugs due to using arc4Random when they really needed a repeatable source (e.g. patterns and lines jump around when you resize things). If it was an easy option, people would use it when appropriate. This would just mean a sub-protocol which has an initializer which takes a seed, and the ability to save/restore state (similar to CGContexts).

I like this kind of layering of functionality and proposals. I would additionally separate the fundamental CSPRNG interface from the fool-proof easy functions that naive users will find on Stack Overflow.

The "easy" functions should:

* Trap on any error without throwing. Sophisticated users may be able to do something about entropy failure, so the fundamental CSPRNG interface needs to provide errors, but the easy function should either degrade somewhat (if entropy is present but insufficient) or just die (if entropy is wholly absent or nearly so).

* Remove the range-less function. Naive users often write things like `Int.random() % 100`, which unbeknownst to them is biased. Providing only the ranged interface nudges naive users toward correct usage. 

* Provide an "easy" way to get some random bytes instead of a random number. Perhaps a Data initializer that returns random-filled bytes of the requested length. This helps make up for the lack of a range-less function on FixedWidthInteger.

The "easy" functions should get the best names: Int.random(in:), Data.random(length:), etc. The fundamental CSPRNG interface should have an interface that is less friendly and less discoverable.

Greg Parker     gparker at apple.com <mailto:gparker at apple.com>     Runtime Wrangler

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20171004/1306b371/attachment.html>

More information about the swift-evolution mailing list