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

Reply via email to