<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><br><div><br>On 5 Oct 2017, at 20:23, Ben Cohen via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 5, 2017, at 10:58, Nate Cook via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">The edge case is really the same (empty ranges), it’s about what we do with the edge case. If we include the methods on integer types, usage will look like this:<div class=""><br class=""></div><div class=""><div class=""><font face="SFMono-Regular" class="">&nbsp; &nbsp; let x = Int.random(in: 0..&lt;5) &nbsp; &nbsp; // 3<br class="">&nbsp; &nbsp;&nbsp;let y = Int.random(in: 0..&lt;0) &nbsp; &nbsp; // runtime error</font></div><div class=""><br class=""></div></div></div></div></blockquote><div><br class=""></div><div><div>These examples are a bit misleading, because they use literals. &nbsp;Sometimes they will, sure, but in practice, many use cases would define Int.random(in: 0..&lt;array.count) or similar, which has just the same pitfalls as array.random().</div><div><br class=""></div><div>p.s. ideally Int.random(in: 0..&lt;0) would be a compile time error...</div><div><br class=""></div></div><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class="">If we only have the collection methods, usage will look like this:</div><div class=""><br class=""></div><div class=""><div class=""><font face="SFMono-Regular" class="">&nbsp; &nbsp; let x = (0..&lt;5).random()! &nbsp; &nbsp; &nbsp; &nbsp; // 3<br class="">&nbsp; &nbsp;&nbsp;let y = (0..&lt;0).random()! &nbsp; &nbsp; &nbsp; &nbsp; // runtime error</font></div><div class=""><br class=""></div></div></div></div></div></blockquote><div><br class=""></div><div>I don’t know if it’s a given that we must make randomElement optional. I’m on the fence as to whether it should be optional vs trap on empty.&nbsp;</div></div></div></blockquote><div><br></div><div>I vote for making them optional because doing otherwise would be inconsistent with first and last, no?</div><br><blockquote type="cite"><div><div><div>Another option is to shadow randomElement on closed range to be non-optional.</div><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class=""><div class=""><div class="">But my suspicion is that lots of people will write things like this:</div></div><div class=""><br class=""></div><div class=""><div class=""><font face="SFMono-Regular" class="">&nbsp; &nbsp;&nbsp;guard&nbsp;let x = (0..&lt;5).random()&nbsp;</font></div><div class=""><font face="SFMono-Regular" class="">&nbsp; &nbsp; &nbsp; &nbsp; else { fatalError("not gonna happen")&nbsp;</font><span style="font-family: SFMono-Regular;" class="">}</span></div><div class=""><br class=""></div><div class="">I’d rather have the numeric methods trap than add the optional unwrapping step to every one of these calls. For me, getting a random number and picking a random element of a collection are two different operations—where it’s common to work with empty collections, especially in generic code, trying to get a random value from an empty range is really a programming error. I think it’s okay for them to have slightly different semantics.</div><div class=""><br class=""></div><div class="">Nate</div><div class=""><br class=""></div><div class=""><br class=""></div><blockquote type="cite" class=""><div class="">On Oct 5, 2017, at 12:27 PM, Alejandro Alonso &lt;<a href="mailto:aalonso128@outlook.com" class="">aalonso128@outlook.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class="">

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" class="">

<div dir="auto" class="">
Rather 0 ..&lt; 0 my bad. I think if we include closedcountable, then there needs to be support for countable, but there are edge cases where users can input invalid ranges for countable.&nbsp;<br class="">
<br class="">
<div class="">Enviado desde mi iPhone</div>
<div class=""><br class="">
El oct. 5, 2017, a la(s) 12:22, Alejandro Alonso via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; escribió:<br class="">
<br class="">
</div>
<blockquote type="cite" class="">
<div class="">I agree with Ben here because users can still enter an invalid range with the static function. I.E. Int.random(in: 0 ... 0).&nbsp;
<div class="">I would really prefer excluding these static functions from numeric types.<br class="">
<br class="">
<div class="">- Alejandro</div>
<div class=""><br class="">
El oct. 5, 2017, a la(s) 12:03, Nate Cook via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; escribió:<br class="">
<br class="">
</div>
<blockquote type="cite" class="">
<div class="">
<div class="">
<blockquote type="cite" class="">
<div class="">On Oct 5, 2017, at 11:30 AM, Ben Cohen via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div>
<div class="">
<div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<br class="">
<div class="">
<blockquote type="cite" class="">
<div class="">On Oct 4, 2017, at 9:12 PM, Chris Lattner via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div>
<br class="Apple-interchange-newline">
<div class="">
<div class="Singleton" style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;">
<div class="">
<blockquote type="cite" class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px;">
<div class="">
<div class="">
<div class="">
<div class="gmail_quote">
<div dir="auto" class="">```</div>
<div dir="auto" class="">extension Int {</div>
<div dir="auto" class="">&nbsp; static func random(in range: Countable{Closed}Range&lt;Int&gt;) -&gt; Int</div>
<div dir="auto" class="">}</div>
</div>
</div>
</div>
</div>
</blockquote>
<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="">
<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="">
Nice. &nbsp;Should these be initializers like:</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="">
<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="">
extension Int {</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="">
&nbsp; init(randomIn: Countable{Closed}Range&lt;Int&gt;)</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>
</div>
<br class="Apple-interchange-newline">
</div>
</blockquote>
</div>
<br class="">
<div class="">I don’t see much of a case for making it it random(in: SpecificCollection) instead of genericCollection.random().</div>
</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
<div class="">I see a couple points in favor of these static methods (or initializers) on the numeric types:</div>
<div class=""><br class="">
</div>
<div class="">1) The collection method will need to return an optional to match the semantics of existing methods (like min()). If this is the only method available, every time someone needs a random value in the range 1...10, they’ll need to unwrap the result (with
 either force unwrapping, which people will complain about, or some kind of conditional binding, which is its own problem). Even if the semantics are the same (trapping on an empty range), the user experience of using a non-optional method will be better.</div>
<div class=""><br class="">
</div>
<div class="">2) Floating-point ranges won’t get the collection method, so either we’ll have inconsistent APIs (random FP value is non-optional, random integer is optional) or we’ll make the FP API optional just to match. Both of those seem bad.</div>
<div class=""><br class="">
</div>
<blockquote type="cite" class="">
<div class="">
<div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div class="">One possible reason is if you exclude half-open ranges, only having CountableClosedRange, then you don’t have to account for the possibility of an empty collection (via an optional or a trap) because they cannot be empty. But closed ranges aren’t
 the currency type – half-open ranges are. So it’d hit usability if you have to convert from one to t'other often.</div>
</div>
</div>
</blockquote>
<div class="">
<blockquote type="cite" class=""><br class="">
</blockquote>
</div>
<blockquote type="cite" class="">
<div class="">
<div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">
<div class="">Other possibility is discovery. But given the common use case is “random element from collection”, I don’t expect this to be an issue as it will quickly become common knowledge that this feature is available.</div>
</div>
</div>
</blockquote>
<div class=""><br class="">
</div>
</div>
Agreed here—I don’t think discovery is really an issue between the two kinds. However, I don’t think the overlap in features (two ways to generate random integers) are a problem, especially as we’d have better alignment between integer and floating-point methods.
<div class=""><br class="">
</div>
<div class="">Nate</div>
</div>
</blockquote>
<blockquote type="cite" class="">
<div class=""><span class="">_______________________________________________</span><br class="">
<span class="">swift-evolution mailing list</span><br class="">
<span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class="">
<span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class="">
</div>
</blockquote>
</div>
</div>
</blockquote>
<blockquote type="cite" class="">
<div class=""><span class="">_______________________________________________</span><br class="">
<span class="">swift-evolution mailing list</span><br class="">
<span class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a></span><br class="">
<span class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br class="">
</div>
</blockquote>
</div>

</div></blockquote></div><br class=""></div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>