> On Jan 11, 2018, at 9:17 PM, Alejandro Alonso <aalonso...@outlook.com> 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. 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.
I would co-sign all of this except for preserving Int.random() and Double.random(), for the reasons I’ve laid out before, those Xiaodi responded with, and even the ergonomics of writing and reading code: - For floating-point values, if someone wants a [0, 1) range, I see no problem with having them write `Double.random(in: 0..<1)`. That’s still nice and short, and there’s no question about what kind of values are produced. - For integers, I see a basic breakdown into two use cases. First, there’s the case where you need a number in a specific range, for which the range-based methods are perfect. When you instead need a full-width integer, you’re generally using that integer as data, rather than as a value. The signedness of `Int` is a pain in that case, so you could either write `UInt64.random(in: .min ... .max)` or else access data from whatever generator you’re using—`Random.default.next()`. Also, from a discoverability and documentation perspective, I like having static `random` methods on the types that they generate. That feels like an easier pattern for a developer to recognize and use. Nate > - Alejandro > > On Jan 8, 2018, 1:02 PM -0600, Nate Cook via swift-evolution > <swift-evolution@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@swift.org <mailto:swift-evolution@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 >>> <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@swift.org <mailto:swift-evolution@swift.org>> wrote: >>> >>>> >>>>> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution >>>>> <swift-evolution@swift.org <mailto:swift-evolution@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@swift.org <mailto:swift-evolution@swift.org> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org <mailto:swift-evolution@swift.org> >>> https://lists.swift.org/mailman/listinfo/swift-evolution >>
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution