<div dir="ltr">On Tue, Jan 2, 2018 at 10:19 AM, Dave DeLong via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><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">Just skimmed through the updated proposal and am weighing in with my naïve opinions:<div><br></div><div><ul class="m_-9136011325329631433MailOutline"><li>I’m still highly skeptical of a static “T.random” API. I’ve yet to see a convincing example where it’d be useful to pick a value from the range of all possible values. The only truly useful one I’ve seen is “pick a random bool”, which could easily be done via “[true, false].random()&quot;<br><br></li><li>I much prefer the GameplayKit API[0], which breaks the idea of randomness up in to 2 separate concepts:</li><ul><li>A “Source” → Where the random numbers come from</li><li>A “Distribution” → Initialized with a source, it makes sure the produced numbers exhibit a specific distribution over multiple samplings. Ie, a uniform distribution vs a Gaussian distribution, or something like “I want to pick a card from a deck but bias choices towards Spades or Aces”. I’m also reminded of the anecdote of how iTunes had to modify their “playlist shuffle” algorithm to be less random[1], because the true randomness would do weird things that made it seem not random. Spotify had the same problem and solution[2].</li><li>Breaking things up like this would also make it easier to test randomness (by using a replay-able source) but that still follow the parameters of your app (that it has a bell-curve distribution of probabilities, for example)<br><br></li></ul><li>I’d still really really really like to see how this could be done as two separate things:</li><ul><li>A minimal implementation in the Standard Library (like, defining the base Source and Distribution protocols, with a single default implementation of each)</li><li>A proposal for a more complete “non-standard library” where the larger array of functionality would be contained. For example, IMO I don’t think the shuffling stuff needs to be in the standard library. This is also where all the cryptographically secure stuff (that your typical app developer does not need) would live.<br><br></li></ul><li>The “random” element of a collection/range should be “func random() → Element?”, not “var random: Element?”. Property values shouldn&#39;t change between accesses. Ditto the static “Randomizable.random” property.<br><br></li><li>What do you think about actively discouraging people from using the modulo operator to create a range? It could be done by having the RNGs return a “RandomValue&lt;T&gt;” type, then defining a mod operator that takes a RandomValue&lt;T&gt; and a T (?), and then giving it a deprecation warning + fixit. Not sure if that’d be worth the type overhead, but I’m very much in favor of encouraging people towards better practices.<br><br></li><li>I’m +1 on crashing if we can’t produce a random number. <br><br></li><li>What do you think about the philosophical difference of Type.random(using:) vs Type.init(randomSource:)?</li></ul><div><br></div><div>Dave</div><div><br></div><div>[0]: <a href="https://developer.apple.com/documentation/gameplaykit/gkrandom" target="_blank">https://developer.apple.<wbr>com/documentation/gameplaykit/<wbr>gkrandom</a></div><div>[1]: <a href="https://www.youtube.com/watch?v=lg188Ebas9E&amp;feature=youtu.be&amp;t=719" target="_blank">https://www.youtube.com/<wbr>watch?v=lg188Ebas9E&amp;feature=<wbr>youtu.be&amp;t=719</a></div><div>[2]: <a href="https://labs.spotify.com/2014/02/28/how-to-shuffle-songs/" target="_blank">https://labs.spotify.com/<wbr>2014/02/28/how-to-shuffle-<wbr>songs/</a></div><div><br></div></div></div></blockquote><div><br></div><div><br></div><div>I think these are some excellent points. Earlier, I think, others also emphasized this idea of exploring what a really minimal implementation in the standard library would look like, and I&#39;ve been thinking about this overnight.</div><div><br></div><div>There is much that is commendable about Alejandro&#39;s proposal, but I agree that there is more than needs to be in the standard library. Here&#39;s what I think the shape of a minimal API would look like, which would simultaneously enable others to implement their desired functionality as an end user:</div><div><br></div><div>- We need very performant, but otherwise barebones, access to system randomness so that it can be a building block for everything else. Because this is so special in that it cannot be seeded or initialized, unlike other RNGs, we don&#39;t need this to be a type, and it doesn&#39;t need to conform to a `RandomNumberGenerator` protocol. It can be as straightforward as one or both of:</div><div><br></div><div>-- A global `func random() -&gt; UInt32`, which is essentially `arc4random` on macOS/iOS and reads from an appropriate secure source on Linux and other platforms. One pro of having such a method is that it&#39;s a drop-in replacement for `arc4random()` that&#39;s _very_ convenient as a primitive to build up other random operations; one con is that it encourages modulo bias, although fortunately mostly only with UInt32.</div><div>-- An extension method on `UnsafeMutableRawBufferPointer` named `func copyRandomBytes()`. This would look a lot like Apple&#39;s `SecCopyRandomBytes` and BSD&#39;s `arc4random_buf`.</div><div><br></div><div>- Having established the primitive, then we can ask what is the minimum _useful_ functionality for an end user. I think the answer is a very judicious subset of the currently proposed functionality:</div><div><br></div><div>-- An extension method or property (`random()` or `random`) on `RandomAccessCollection`.</div><div>-- An extension method or property (`random()` or `random`) on `Range where Bound : SignedInteger`, `Range where Bound : UnsignedInteger`, `Range where Bound : BinaryFloatingPoint`.</div><div><br></div><div>- One advantage of abandoning `Randomizable` and spellings like `Int.random` and `Double.random` is limiting possible modulo bias in using the former, and also eliminating the lack of semantic guarantees about the implicit bounds (which for Int are Int.min...Int.max, but for Double must be 0..&lt;1). There can be no confusion about `(0.0..&lt;1.0).random`.</div><div>- An advantage inherent to abandoning the `randomIn:` or `random(in:)` spelling is that users must now explicitly address what to do about an empty range, which in my view is better than an implicit trap that may or may not happen deterministically during testing.<br></div><div>- A final advantage over the current proposal is that we collapse three very similar spellings with subtle usage differences but entirely overlapping functionality--`Int.random`, `Int.random(in:)`, and `Range.random`--into one with well-defined semantics. A user learns once and can have good understanding of others&#39; code and write their own without hidden pitfalls.</div><div><br></div><div>The end result of such a minimalist design is that we introduce no new types, no new protocols, and only three or four new functions. They all have very defined semantics, and together they enable both basic use and provide the building blocks for advanced users to create their own PRNGs that fit their advanced cryptographic or non-cryptographic needs.</div><div><br></div><div>Thoughts?</div><div><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><div></div><div><blockquote type="cite"><div><div class="h5"><div>On Jan 2, 2018, at 1:35 AM, Alejandro Alonso via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_-9136011325329631433Apple-interchange-newline"></div></div><div><div><div class="h5">




<div>
<div name="messageBodySection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif">
Hello swift evolution once again, I’ve been hard at work considering every email and revising the proposal. I’ve made lots of changes and additions to the proposal to discuss some problems we’ve had (T.random), and walks through detailed design. You can see
 the proposal here: <a href="https://github.com/apple/swift-evolution/pull/760" target="_blank">https://github.com/<wbr>apple/swift-evolution/pull/760</a><wbr> .
<div><br>
</div>
<div>A big issue that lots of people pointed out was `T.random %` and to remove it completely from the API. To give a gist of why I continue to support T.random:</div>
<div><br>
</div>
<div>1. Modulo bias misuse is only a problem to types that conform to `BinaryInteger`. Why remove this functionality if only a portion of the types have the ability of misuse. `Double.random % 10` is a good example of where modulo isn’t implemented here as
 it produces the error, “&#39;%&#39; is unavailable: Use truncatingRemainder instead”.</div>
<div><br>
</div>
<div>2. `Int.random(in: Int.min … Int.max)` doesn’t work. For developers that actually rely on this functionality, the work around that was discussed earlier simply doesn’t work. `Int.min … Int.max`’s count property exceeds that of `Int`’s numerical range.
 A working work around would be something along the lines of `Int(truncatingIfNeeded: Random.default.next(UInt.self)<wbr>)` which creates a pain point for those developers. As the goal of this proposal to remove pain points regarding random, this change does the
 opposite.</div>
<div><br>
</div>
<div>I’m interested to hear if anymore discussion around this, or any other issues come up.</div>
</div>
<div name="messageSignatureSection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif">
<br>
- Alejandro</div>
<div name="messageReplySection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif">
<br>
On Sep 8, 2017, 11:52 AM -0500, Alejandro Alonso via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;, wrote:<br>
<blockquote type="cite" style="margin:5px 5px;padding-left:10px;border-left:thin solid #1abc9c">
<div name="messageBodySection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif">
Hello swift evolution, I would like to propose a unified approach to `random()` in Swift. I have a simple implementation here <a href="https://gist.github.com/Azoy/5d294148c8b97d20b96ee64f434bb4f5" target="_blank">https://gist.github.com/<wbr>Azoy/<wbr>5d294148c8b97d20b96ee64f434bb4<wbr>f5</a>.
 This implementation is a simple wrapper over existing random functions so existing code bases will not be affected. Also, this approach introduces a new random feature for Linux users that give them access to upper bounds, as well as a lower bound for both
 Glibc and Darwin users. This change would be implemented within Foundation.
<div><br>
</div>
<div>I believe this simple change could have a very positive impact on new developers learning Swift and experienced developers being able to write single random declarations.</div>
<div><br>
</div>
<div>I’d like to hear about your ideas on this proposal, or any implementation changes if need be.</div>
<div><br>
</div>
<div>- Alejando</div>
</div>
<div name="messageReplySection" style="font-size:14px;font-family:-apple-system,BlinkMacSystemFont,sans-serif">
<br>
<div></div>
</div>
</blockquote>
</div>
</div></div></div><span class="">

______________________________<wbr>_________________<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" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br></span></div></blockquote></div><br></div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div></div>