<div><br><div class="gmail_quote"><div dir="auto">On Wed, Oct 4, 2017 at 20:49 Greg Parker via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><br><div><blockquote type="cite"><div>On Oct 3, 2017, at 11:44 PM, Jonathan Hull via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br class="m_7560581448019464507Apple-interchange-newline"><div><div style="word-wrap:break-word">I like the idea of splitting it into 2 separate “Random” proposals.<div><br></div><div>The first would have Xiaodi’s built-in CSPRNG which only has the interface:</div><div><br></div><div>On FixedWidthInteger:</div><div><span class="m_7560581448019464507Apple-tab-span" style="white-space:pre-wrap">        </span>static func random()throws -> Self</div><div><span class="m_7560581448019464507Apple-tab-span" style="white-space:pre-wrap">        </span>static func random(in range: ClosedRange<Self>)throws -> Self<br><div><br></div><div>On Double:</div><div><span class="m_7560581448019464507Apple-tab-span" style="white-space:pre-wrap">        </span>static func random()throws -> Double</div><div><span class="m_7560581448019464507Apple-tab-span" style="white-space:pre-wrap">        </span>static func random(in range: ClosedRange<Double>)throws -> Double</div><div><br></div><div>(Everything else we want, like shuffled(), could be built in later proposals by calling those functions)</div><div><br></div><div>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).</div></div></div></div></blockquote></div><div><blockquote type="cite"><br></blockquote></div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div>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.</div><div><br></div><div>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).</div></div></div></div></blockquote></div><div><br></div></div><div style="word-wrap:break-word;line-break:after-white-space"><div>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.</div><div><div><br></div><div>The "easy" functions should:</div><div><br></div></div><div>* 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).</div><div><br></div><div>* 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. </div><div><br></div><div>* 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.</div><div><br></div><div>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.</div></div><div style="word-wrap:break-word;line-break:after-white-space"><div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">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).</div><div dir="auto"><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word;line-break:after-white-space"><div><br></div><div><br></div><div>-- </div><div>Greg Parker <a href="mailto:gparker@apple.com" target="_blank">gparker@apple.com</a> Runtime Wrangler</div><div><br></div><div><br></div></div>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
</blockquote></div></div>