I pushed some updates to the proposal with a reflected API, but I do not agree 
that we should rid the API of T.random just because some users will misuse it. 
I think the correct solution here is to include T.random(in:) (which does not 
return an optional making it not a second typing of (min ... max).random). Like 
Jonathon said, autocomplete will display both of these and users will be able 
to select random(in:). I also disagree that T.random is _always_ followed by 
modulo because if we look at arc4random() it’s range is the whole domain of 
UInt32. Users don’t put a modulo here because they know the correct way to do 
it is through arc4random_uniform(), either through online tutorials, or by 
reading documentation. If we did get rid of T.random, users who want a random 
byte for instance would have to write UInt8.random(in: 0 … 255) every time. 
Developers will make wrappers over this. I believe the correct solution is to 
keep T.random for those who won’t misuse it and T.random(in:) for those who 
need to a random value within a range.

- Alejandro

On Nov 17, 2017, 5:09 PM -0600, Xiaodi Wu <[email protected]>, wrote:
On Fri, Nov 17, 2017 at 10:10 AM, Gwendal Roué via swift-evolution 
<[email protected]<mailto:[email protected]>> wrote:

> Le 17 nov. 2017 à 16:04, Alejandro Alonso via swift-evolution 
> <[email protected]<mailto:[email protected]>> a écrit :
>
> If we go back to your example, you never call FixedWidthInteger.random 
> either, you call range.random. Does this mean integer types shouldn’t have 
> .random? No, because it means get a random number from it’s internal range 
> (alias to (min ... max).random). I think we can all agree that Integer.random 
> is a nicer api than making a range of its bounds. The same goes for 
> Date.random and Color.random.
>
> - Alejandro

Hello,

I'm not random expert, but it has never happened in my developer life (backend 
& frontend app developer) that I have used a pure random value from the full 
domain of the random type. In this life:

- Int.random is _always_ followed by % modulo. Unless the better 
arc4random_uniform(max) is used.
- Color.random is _never_ used, because random colors look bad.
- Date.random is _never_ used, because time is a physical unit, and random 
points in time do not match any physical use case.

This does not mean that random values from the full domain are useless. Of 
course not: math apps, fuzzers, etc. need them.

Yet a range-based API would be much welcomed by regular app developers. And 
also Array.randomElement(), Array.shuffled(), etc, because there are plenty 
naive and bad algorithms for those simple tasks.

Certainly it's hard to defend Date.random (and yes, it might be useful for a 
fuzzer, but that's a very niche use case--and in that case the fuzzer should 
probably also generate invalid/non-existent dates, which surely Date.random 
should not do). But actually, Int.random followed by % is the much bigger issue 
and a very good cautionary tale for why T.random is not a good idea. Swift 
should help users do the correct thing, and getting a random value across the 
full domain and computing an integer modulus is never the correct thing to do 
because of modulo bias, yet it's a very common error to make. We are much 
better off eliminating this API and encouraging use of the correct API, thereby 
reducing the likelihood of users making this category of error.

If (and I agree with this) the range-based notation is less intuitive 
(0..<10.random is certainly less discoverable than Int.random), then we ought 
to offer an API in the form of `Int.random(in:)` but not `Int.random`. This 
does not preclude a `Collection.random` API as Alejandro proposes, of course, 
and that has independent value as Gwendal says.

_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to