On Wed, Oct 4, 2017 at 21:01 Xiaodi Wu <xiaodi...@gmail.com> wrote: > On Wed, Oct 4, 2017 at 20:49 Greg Parker via swift-evolution < > swift-evolution@swift.org> wrote: > >> >> On Oct 3, 2017, at 11:44 PM, Jonathan Hull via swift-evolution < >> swift-evolution@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. >> > > Agree, this is a very tractable set of functions for an initial > implementation. In fact, with these primitives and maybe some shuffling and > choosing conveniences in the stdlib, I see the remainder as useful-to-haves > that may or may not be critical for inclusion in the stdlib vs more > appropriate for a dedicated math library (more to follow on that thought in > a little while). >
To sum up my thoughts so far in code, building on previous comments from others, this would be a nice set of random APIs, IMO: ``` extension Int { static func random(in range: Countable{Closed}Range<Int>) -> Int } // And similar for other concrete built-in integer types. // // Since fixed-width integers could exceed the maximum size supported by getrandom() // and other such functions, we do not provide a default implementation. // // The return value may not be cryptographically secure if there is insufficient entropy. extension Float { static func random(in range: {Closed}Range<Float>) -> Float } extension Double { static func random(in range: {Closed}Range<Double>) -> Double } extension Float80 { // Ditto. } extension Data { static func random(byteCount: Int) -> Data } extension UnsafeMutableRawPointer { func copyRandomBytes(count: Int) throws } // This function is to be the most primitive of the random APIs, and will throw if there is insufficient entropy. extension UnsafeMutableRawBufferPointer { func copyRandomBytes() throws } // Just as UMRBP.copyBytes(from:) parallels UMRP.copyBytes(from:count:), we offer this convenience here. ``` > >> >> -- >> Greg Parker gpar...@apple.com Runtime Wrangler >> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution