We are doing crazy contortions to avoid the 'random % 100’ issue. Why not just check for that pattern and issue a warning with a fixit to do it better?
I don’t think it is worth handicapping everything just to avoid this. Thanks, Jon > On Jan 11, 2018, at 11:22 PM, Nate Cook via swift-evolution > <[email protected]> wrote: > >> On Jan 11, 2018, at 9:17 PM, Alejandro Alonso <[email protected] >> <mailto:[email protected]>> 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 >> <[email protected] <mailto:[email protected]>>, 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 >>>> <[email protected] <mailto:[email protected]>> 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 >>>> <[email protected] <mailto:[email protected]>> wrote: >>>> >>>>> >>>>>> On Dec 2, 2017, at 6:02 PM, Xiaodi Wu via swift-evolution >>>>>> <[email protected] <mailto:[email protected]>> 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 nameinsecureRandom 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 >>>>> [email protected] <mailto:[email protected]> >>>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>>> _______________________________________________ >>>> swift-evolution mailing list >>>> [email protected] <mailto:[email protected]> >>>> https://lists.swift.org/mailman/listinfo/swift-evolution >>>> <https://lists.swift.org/mailman/listinfo/swift-evolution> >>> > > _______________________________________________ > swift-evolution mailing list > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
