<div><br><div class="gmail_quote"><div dir="auto">On Tue, Jan 9, 2018 at 05:12 Jonathan Hull via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; 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">Some thoughts:<div><br></div><div>- How do I randomly select an enum?<br><div><br></div><div>- I like that RandomNumberGenerator doesn’t have an associated type. I agree that we should just spit out UInt64s for simplicity.</div><div><br></div><div>- I don’t like how it is so closely tied with Range.  I realize that both Int and Float work with Ranges, but other random types do not (e.g. CGVectors).  You are special casing FixedWidthInteger and BinaryFloatingPoint, which are very important… but we lose the ability to deal with other randomly generated types.</div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">So, I’ll defend this design. At some point, you need to expose the primitive operation, which is the selection of a random *number* within a range, and after our very lengthy discussions, this is the best spelling in Swift by consensus.</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"><div><div></div></div></div></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div><div>- Following on the previous point, I don’t like that the code for dealing with Integers/Floats is in Range.  It feels like things aren’t properly encapsulated. </div><div><br></div><div>- Why bother supporting non-closed Ranges at all?  If you only allow closed ranges, then you can’t end up with an empty range. The only difference in behavior I can think of is on floating point, but I can’t think of a use-case where excluding the supremum is actually useful in any real world way.</div><div></div></div></div></blockquote><div dir="auto"><br></div><div dir="auto">This is a nontrivial thing to get right; in fact, in C++, many implementations of the standard library got it wrong for quite some time. Additionally, generating a value in 0..&lt;1 is a primitive operation which is equivalent, essentially, to generating a random significand, so it is important to expose this functionality in the standard library.</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"><div dir="auto">- This may sound strange, but I would <i>really</i> like to see Bool handled as a default implementation on the generator protocol itself.  On my own version of this I have both the ‘coinFlip()’ and ‘oneIn(_ num:Int)’ methods which I find extremely useful.  CoinFlip just gives you a random bool, whereas you can say things like oneIn(100) to get ‘true’ roughly 1 out of every 100 times you call it.  These are useful for branching randomly.  They are most useful on the source/generator itself because it is ergonomic when you need to rewind the source.</div></div></blockquote><div dir="auto"><br></div><div dir="auto">This is a Bernoulli distribution. Which is a trivial distribution to implement—if you have a primitive that gives you a random value in the range 0..&lt;1! (See, this is why you need that as a primitive.) Then, for example, a fair coin is obtained by binning 0..&lt;0.5 as heads and 0.5..&lt;1 as tails. Adjust to taste for your desired value of p.</div><div dir="auto"><br></div><div dir="auto">However, more below on distributions.</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"><div dir="auto"></div><div dir="auto">- IMO distributions should be sources/generators themselves which just wrap another source.  We could have a subprotocol of RandomNumberGenerator which just semantically guarantees uniform distribution, and then distributions that need it could be sure of the input distribution.  Notice this doesn’t limit the distribution to only be used for Integers as they are in the demo. They can be used anywhere a source can be used.</div></div></blockquote><div dir="auto"><br></div><div dir="auto">One of the major critiques of the C++ design is its overcomplicated design, one aspect of which is this wrapping of sources. Some people might like it or find it to be their preferred design, but given that there’s some consensus that the uniform distribution is all we’re offering in the standard library (with everything else being more appropriate for a third-party library that’s more elaborate), this is a design decision that each such third-party library can decide for itself.</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"><div dir="auto"></div><div dir="auto">- Having a subprotocol for generators which can be rewound is extremely important for entire classes of real-world problems.  I have spent a lot of time using this and it solves a LOT of problems. For example, I have a Lorem Ipsum Generator which takes Attributes and a CGSize to fill.  It works by branching (using the Bool methods above) and then rewinding bits which don’t fit (If you just futz with the last part instead of generating appropriate clauses, it won’t look right).  I also have a bunch of backtracking algorithms which rely on this rewind ability.  Plus numerous visual effects which rely on a repeatable rewindable source.</div><div dir="auto"><span class="m_5929681624520105407Apple-tab-span" style="white-space:pre-wrap">        </span><i>- Tl;dr: It isn’t enough to just have a seed, you need to be able to mark a state of a generator and return to that state later.</i></div><div dir="auto"><br></div><div dir="auto"><span class="m_5929681624520105407Apple-tab-span" style="white-space:pre-wrap">        </span>My RepeatableRandomSource Protocol has 3 extra methods:</div><div dir="auto"><span class="m_5929681624520105407Apple-tab-span" style="white-space:pre-wrap">        </span>- It takes a seed</div><div dir="auto"><span class="m_5929681624520105407Apple-tab-span" style="white-space:pre-wrap">        </span>- It has a mark() method which returns a token</div><div dir="auto"><span class="m_5929681624520105407Apple-tab-span" style="white-space:pre-wrap">        </span>- It has a returnToMark(_ mark:Mark) method which takes a token and restores the appropriate state </div></div></blockquote><div dir="auto"><br></div><div dir="auto">This too is one of those features that, given how we’re not offering any such RNGs in the standard library, can be a decision for custom libraries to design in a way that most suits themselves. Many RNGs can be seeded and reseeded, but not all can be rewound or skipped ahead, so it’s something where the ultimate hierarchy of protocols and their methods will depend on the concrete types on offer.</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"><div dir="auto"></div><div dir="auto">- I really appreciate that you made a playground :-)</div><div dir="auto"><br></div><div dir="auto">Thanks,</div><div dir="auto">Jon</div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto"><div><div><div><blockquote type="cite"></blockquote></div></div></div></div></div><div style="word-wrap:break-word"><div><div><div><div><div><blockquote type="cite"><div>On Jan 8, 2018, at 11:02 AM, Nate Cook via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_5929681624520105407Apple-interchange-newline"></blockquote></div></div></div></div></div></div><div style="word-wrap:break-word"><div><div><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space">I created a playground to explore this question, starting with a minimal subset of the proposal’s additions and building from there. The attached playground demonstrates what’s possible with this subset on the first page, then uses subsequent pages to explore how the main random facilities of the C++ STL work under this model. (In my opinion, they work pretty well!)<div><br></div><div>The subset in the playground has three main differences from the proposal:</div><div> - It doesn&#39;t include a <font face="Menlo">Randomizable</font> protocol or a <font face="Menlo">random</font> property on numeric types.<br> - It doesn&#39;t include the static <font face="Menlo">random(in:)</font> methods on numeric types, either.<br> - The <font face="Menlo">RandomNumberGenerator</font> protocol doesn&#39;t have an associated type. Instead, it requires all conforming types to produce <font face="Menlo">UInt64</font> values.<br><br></div><div>I’ve tried to include a bit of real-world usage in the playground to demonstrate what writing code would look like with these additions. Please take a look!</div><div><br></div><div>Nate</div><div><br></div><div></div></div></div></blockquote></div></div></div></div></div></div><div style="word-wrap:break-word"><div><div><div><div><div><blockquote type="cite"><div><span id="m_5929681624520105407cid:ABC18921-24CA-48D8-BC24-C1F445F8C252@hsd1.ca.comcast.net.">&lt;Random.playground.zip&gt;</span></div></blockquote></div></div></div></div></div></div><div style="word-wrap:break-word"><div><div><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word;line-break:after-white-space"><div></div><div><br></div><div><div><blockquote type="cite"><div>On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_5929681624520105407Apple-interchange-newline"><div><div dir="auto">I don’t have much to say about this other than that I think the discussion seems way too narrow, focusing on spelling rather than on functionality and composability.  I consider the “generic random number library” design to be a mostly-solved problem, in <span style="background-color:rgba(255,255,255,0)">the C++ standard library (<a href="http://en.cppreference.com/w/cpp/numeric/random" target="_blank">http://en.cppreference.com/w/cpp/numeric/random</a>).  </span>Whatever goes into the Swift standard library does not need to have all those features right away, but should support being extended into something having the same general shape. IMO the right design strategy is to <u>implement and use</u> a Swift version of C++’s facilities and only then consider proposing [perhaps a subset of] that design for standardization in Swift.<div><div><br></div><div>Sent from my iPad<div><br>On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><br><div><blockquote type="cite"><div>On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br class="m_5929681624520105407Apple-interchange-newline"><div><span 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;float:none;display:inline!important">Instead, we ought to make clear to users both the features and the limitations of this API, to encourage use where suitable and to discourage use where unsuitable.</span></div></blockquote></div><br><div>I like that you&#39;re considering the balance here. I&#39;ve been lightly following this thread and want to add my thoughts on keeping crypto and pseudorandomness out of the name of at least one <font face="Menlo">random</font> API intended for general use.</div><div><br></div><div>For someone who doesn&#39;t know or care about the subtleties of insecure or pseudorandom numbers, I&#39;m not sure that the name <font face="Menlo">insecureRandom</font> is effectively much different than <font face="Menlo">badRandom</font>, at least in terms of the information it conveys to non-experts. To Greg&#39;s point, that&#39;s the opposite of the signal that the API name should suggest because it&#39;s what most people should use most of the time. As you say, this API is being designed for general use.</div><div><br></div><div>There&#39;s a cost to adding extra complexity to names, too. I don&#39;t think it&#39;s far-fetched to suspect that people who find <font face="Menlo">insecureRandom</font> in an autocomplete listing or search will think &quot;Where&#39;s the plain random function?&quot;... and then go looking for a community extension that will inevitably provide a trivial alias: <font face="Menlo">func random() { return insecureRandom() }</font>. That&#39;s the sort of adoption I&#39;d expect from something for new programmers, like Swift Playgrounds. Someone&#39;s introduction to randomness in programming should probably involve no more than a straightforward mapping from the elementary definition, rather than forcing a teaching moment from more advanced math.</div><div><br></div><div>I think there are better places for caveat information than in the API names themselves; documentation being one clear destination. This is in contrast with <font face="Menlo">Unsafe*Pointer</font>, where the safety element is critical enough to be elevated to be more than caveat-level information. You can go really far and create really cool things before these caveats start to apply. Using randomness as a black box in an intro programming environment seems like a much more common scenario than someone attempting to roll their first crypto by only reading API names and hoping for the best.</div><div><br></div><div>-Kyle</div></div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div></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" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></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" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div></div></div></div></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>