[swift-evolution] [Proposal] Random Unification

Xiaodi Wu xiaodi.wu at gmail.com
Thu Jan 11 21:27:41 CST 2018


On Thu, Jan 11, 2018 at 9:17 PM, Alejandro Alonso via swift-evolution <
swift-evolution at swift.org> wrote:

> Sorry it takes me forever to respond! I finally got around to writing
> this! School really takes all my time x)
>
> I have a few ideas on where we can go with this:
>
> 1. I agree, we should ditch `Randomizable` as something like that should
> belong in a separate library or written by the user.
>
> 2. I also agree we should ditch the associated type on
> `RandomNumberGenerator`. I think we can sacrifice 32 bit generators using
> 64 bit ints to conform to the core team’s general use policy. This also
> makes default arguments for rngs possible which is a +1 for me!
>
> I start to drift off from your design because `.random()` being an
> exception to ranges in that it’s inconsistent with other collection
> facilities and collection `.random()`. You make a few emails in the past
> that reference this as well. I think the right move is to have the static
> functions utilize the ranges to provide non optional types.
>
> You wrote:
>
>> I see a couple points in favor of these static methods (or initializers)
> on the numeric types:
>
> 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.
>
>  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.
>>
> I believe this is the direction we need to go to keep consistency with
> collection based methods by justifying `.random(in:)` on the numeric types.
> With that in mind, Ben made a comment a long while ago saying, “The one
> downside is that you’d have to write 0..<Int.max. This might be a
> justification for a static property on one of the Integer protocols as
> shorthand for that.” I believe this makes it perfectly justifiable for
> `.random()` on numeric types. This also creates a consistency with
> `Bool.random()` making it justifiable for this as well.
>
> We can do all of this without `Randomizable` as well! Add extension
> methods on `FixedWidthInteger`, `BinaryFloatingPoint`, and `Bool`. These
> will be the methods that crash on an empty range, but we can precondition
> here to provide helpful debugging for developers. You made reference to
> users using the range based api for a safe alternative if they needed
> optionals.
>
> ```
> // Here you can use something more runtime oriented (such as an array
> count)
> guard let x = (0 ..< 5).random() else {
> fatalError(“not going to happen")
> }
> ```
>
> I’m not too sure if you’ve had a change of heart, but I think the
> following is justifiable if we remove `Randomizable`.
>
> Sample Syntax:
> ```
> // Full Int width (shorthand for Int.random(in: .min … .max))
> Int.random()
>
> // random int from [0, 10)
> Int.random(in: 0 ..< 10)
>
> // random double from [0, 1) (Modulo isn’t an issue here!)
> Double.random()
>
> // random double from [0, .pi)
> Double.random(in: 0 ..< .pi)
>
> // random boolean
> Bool.random()
> ```
>
> This seems very consistent to me. The only inconsistency is with
> `Int.random()` covering the full width, and `Double.random()` covering only
> `[0, 1)`, but to me this functionality is very precedented in many other
> languages. Also by removing `Randomizable`, other data types like `Data`
> don’t have to conform to a protocol, but can just add a random initializer
> that fits its needs.
>
> I think now is when people will start saying, “Int.random() bad, modulo
> bias, no no” x)
> I see the potential for error here, but logically I’m thinking that so
> many other languages have this feature and I wonder if you think they all
> did it wrong too and shouldn’t have done so.
>

You will have noted, surely, the evidence given above that in Apple's
internal code the majority of uses of APIs equivalent to `Int.random()` are
erroneous due to unintended modulo bias. Yes, what that would imply is that
all the other languages did it wrong. Why do you feel it is so important to
have a shorthand that enables no additional behavior in the face of
overwhelming evidence that it is actively harmful?

Likewise, you acknowledge the inconsistency of Int.random() and
Double.random(), yet again suggest a shorthand that enables no additional
behavior in spite of the potential for misunderstanding. What advantage of
having such an API do you see which could overcome this very glaring
drawback?

This type of behavior is found in C, C++, C#, Java, etc. I agree with
> Jonathon in that maybe we could suggest a warning/fixit in Xcode.
>
> tl;dr - Remove `Randomizable`, remove associated type on
> `RandomNumberGenerator`, be consistent with `.random()` with other
> properties and functions with every collection, preserve static `random()`
> and `random(in:)` syntax.
>
> - Alejandro
>
> On Jan 8, 2018, 1:02 PM -0600, Nate Cook via swift-evolution <
> swift-evolution at swift.org>, wrote:
>
> 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!)
>
> The subset in the playground has three main differences from the proposal:
>  - It doesn't include a Randomizable protocol or a random property on
> numeric types.
>  - It doesn't include the static random(in:) methods on numeric types,
> either.
>  - The RandomNumberGenerator protocol doesn't have an associated type.
> Instead, it requires all conforming types to produce UInt64 values.
>
> 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!
>
> Nate
>
>
> On Dec 2, 2017, at 9:50 PM, Dave Abrahams via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> 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 the C++ standard library (
> http://en.cppreference.com/w/cpp/numeric/random).  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 *implement and use* a Swift
> version of C++’s facilities and only then consider proposing [perhaps a
> subset of] that design for standardization in Swift.
>
> Sent from my iPad
>
> On Dec 2, 2017, at 5:12 PM, Kyle Murray via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> 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.
>
>
> I like that you're considering the balance here. I'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 random API intended for
> general use.
>
> For someone who doesn't know or care about the subtleties of insecure or
> pseudorandom numbers, I'm not sure that the name insecureRandom is
> effectively much different than badRandom, at least in terms of the
> information it conveys to non-experts. To Greg's point, that's the opposite
> of the signal that the API name should suggest because it's what most
> people should use most of the time. As you say, this API is being designed
> for general use.
>
> There's a cost to adding extra complexity to names, too. I don't think
> it's far-fetched to suspect that people who find insecureRandom in an
> autocomplete listing or search will think "Where's the plain random
> function?"... and then go looking for a community extension that will
> inevitably provide a trivial alias: func random() { return
> insecureRandom() }. That's the sort of adoption I'd expect from something
> for new programmers, like Swift Playgrounds. Someone'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.
>
> 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 Unsafe*Pointer, 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.
>
> -Kyle
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20180111/8fe15446/attachment.html>


More information about the swift-evolution mailing list