<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Nov 17, 2017, at 3:09 PM, Xiaodi Wu via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">But actually, Int.random followed by % is the much bigger issue and a very good cautionary tale for why T.random is not a good idea. Swift should help users do the correct thing, and getting a random value across the full domain and computing an integer modulus is never the correct thing to do because of modulo bias, yet it's a very common error to make. We are much better off eliminating this API and encouraging use of the correct API, thereby reducing the likelihood of users making this category of error.<br class=""></div><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""></div></div></blockquote><div><br class=""></div><div>Amen.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">If (and I agree with this) the range-based notation is less intuitive (0..<10.random is certainly less discoverable than Int.random), then we ought to offer an API in the form of `Int.random(in:)` but not `Int.random`. This does not preclude a `Collection.random` API as Alejandro proposes, of course, and that has independent value as Gwendal says.</div></div></blockquote></div><div class=""><br class=""></div><div class="">If we're not happy with the range syntax, maybe we should put `random(in:)`-style methods on the RNG protocol as extension methods instead. Then there's a nice, uniform style:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let diceRoll = rng.random(in: 1...6)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let card = rng.random(in: deck)</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let isHeads = rng.random(in: [true, false])</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>let probability = rng.random(in: 0.0...1.0)<span class="Apple-tab-span" style="white-space:pre">        </span>// Special FloatingPoint overload</div><div class=""><br class=""></div><div class="">The only issue is that this makes the default RNG's name really important. Something like:</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>DefaultRandom.shared.random(in: 1...6)</div><div class=""><br class=""></div><div class="">Will be a bit of a pain for users.</div><div class=""><br class=""></div><div class="">Maybe we call the default RNG instance `random`, and then give the `random(in:)` methods another name, like `choose(in:)`?</div><div class=""><br class=""></div><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let diceRoll = random.choose(in: 1...6)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let card = random.choose(in: deck)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let isHeads = random.choose(in: [true, false])</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let probability = random.choose(in: 0.0...1.0)</div></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><div class=""><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let diceRoll = rng.choose(in: 1...6)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let card = rng.choose(in: deck)</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let isHeads = rng.choose(in: [true, false])</div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let probability = rng.choose(in: 0.0...1.0)</div></div></div><div class=""><br class=""></div><div class="">This would allow us to keep the default RNG's type private and expose it only as an existential—which means more code will treat RNGs as black boxes, and people will extend the RNG protocol instead of the default RNG struct—while also putting our default random number generator under the name `random`, which is probably where people will look for such a thing.</div><div class=""><br class=""></div><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">-- </div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>
</div>
<br class=""></body></html>