You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: proposals/0202-random-unification.md
+39-36Lines changed: 39 additions & 36 deletions
Original file line number
Diff line number
Diff line change
@@ -90,39 +90,41 @@ To kick this off, the standard library will provide a default RNG. Each platform
90
90
91
91
For the core API, introduce a new protocol named `RandomNumberGenerator`. This type is used to define RNGs that can be used within the stdlib. Developers can conform to this type and use their own custom RNG throughout their whole application.
92
92
93
-
Then for the stdlib's default RNG implementation, introduce a new struct named `Random`. This struct contains a singleton called `default` which provides access to the methods of `RandomNumberGenerator`.
93
+
Then for the stdlib's default RNG implementation, introduce a new struct named `SystemRandomNumberGenerator`.
94
94
95
95
Next, we will make extension methods for `FixedWidthInteger`, `BinaryFloatingPoint` and `Bool`. For numeric types, this allows developers to select a value within a range and swap out the RNG used to select a value within the range.
96
96
97
97
`FixedWidthInteger` example:
98
98
```swift
99
99
// Utilizes the standard library's default random
100
-
/// (alias to Int.random(in: 0 ..< 10, using: &Random.default))
100
+
// Alias to:
101
+
// var rng = SystemRandomNumberGenerator()
102
+
// Int.random(in: 0 ..< 10, using: &rng)
101
103
let randomIntFrom0To10 =Int.random(in: 0..<10)
102
104
let randomUIntFrom10Through100 =UInt.random(in: 10...100, using: &myCustomRandomNumberGenerator)
103
105
104
106
// The following are examples on how to get full width integers
105
107
106
108
let randomInt =Int.random(in: .min... .max)
107
-
108
-
// an alternative spelling could be:
109
-
// let randomUInt = myCustomRandomNumberGenerator.next()
110
-
// this takes advantage of the fact that generators can produce unsigned integers
111
109
let randomUInt =UInt.random(in: .min... .max, using: &myCustomRandomNumberGenerator)
112
110
```
113
111
114
112
`BinaryFloatingPoint` example:
115
113
```swift
116
114
// Utilizes the standard library's default random
117
-
// (alias to Float.random(in: 0 ..< 1, using: &Random.default))
115
+
// Alias to:
116
+
// var rng = SystemRandomNumberGenerator()
117
+
// Float.random(in: 0 ..< 1, using: &rng)
118
118
let randomFloat =Float.random(in: 0..<1)
119
119
let randomDouble =Double.random(in: 0... .pi, using: &myCustomRandomNumberGenerator)
120
120
```
121
121
122
122
`Bool` example:
123
123
```swift
124
124
// Utilizes the standard library's default random
125
-
// (alias to Bool.random(using: &Random.default))
125
+
// Alias to:
126
+
// var rng = SystemRandomNumberGenerator()
127
+
// Bool.random(using: &rng)
126
128
let randomBool1 =Bool.random()
127
129
let randomBool2 =Bool.random(using: &myCustomRandomNumberGenerator)
128
130
```
@@ -138,7 +140,9 @@ For `Collection` we add an extension method for collections to get a random elem
138
140
let greetings = ["hey", "hi", "hello", "hola"]
139
141
140
142
// Utilizes the standard library's default random
141
-
// (alias to greetings.randomElement(using: &Random.default))
143
+
// Alias to:
144
+
// var rng = SystemRandomNumberGenerator()
145
+
// greetings.randomElement(using: &rng)!
142
146
print(greetings.randomElement()!) // This returns an Optional
143
147
print(greetings.randomElement(using: &myCustomRandomNumberGenerator)!) // This returns an Optional
144
148
```
@@ -158,7 +162,9 @@ As a result of adding the random API, it only makes sense to utilize that power
158
162
var greetings = ["hey", "hi", "hello", "hola"]
159
163
160
164
// Utilizes the standard library's default random
161
-
// (alias to greetings.shuffle(using: &Random.default))
165
+
// Alias to:
166
+
// var rng = SystemRandomNumberGenerator()
167
+
// greetings.shuffle(using: &rng)
162
168
greetings.shuffle()
163
169
print(greetings) // A possible output could be ["hola", "hello", "hey", "hi"]
@@ -379,6 +382,6 @@ There were a bit of discussion for and against this. Initially I was on board wi
379
382
380
383
This was a very heavily discussed topic that we can't skip over.
381
384
382
-
I think we came into agreement that `range.random()` should be possible, however the discussion was around whether or not this is the primary spelling for getting random numbers. Having a range as the primary spelling makes it fairly simple to get a random number from. Ranges are also very desirable because it doesn't encourage modulo bias. Also, since we decided pretty early on that we're going to trap if for whatever reason we can't get a random number, this gave `range.random()` the excuse to return a non optional.
385
+
I think we came into agreement that `range.randomElement()` should be possible, however the discussion was around whether or not this is the primary spelling for getting random numbers. Having a range as the primary spelling makes it fairly simple to get a random number from. Ranges are also very desirable because it doesn't encourage modulo bias. Also, since we decided pretty early on that we're going to trap if for whatever reason we can't get a random number, this gave `range.randomElement()` the excuse to return a non optional.
383
386
384
-
On the other end of the spectrum, we came into early agreement that `Collection.random()` needs to return an optional in the case of an empty collection. If ranges were the primary spelling, then we would need to create exceptions for them to return non optionals. This would satisfy the general use design, but as we agreed that `.random()` behaves more like `.first`, `.last`, `.min()`, and `.max()`. Because of this, `.random()` has to return an optional to keep the consistent semantics. This justifies the static functions on the numeric types as the primary spelling as they can be the ones to return non optionals. These static functions are also the spelling for how developers think about going about random numbers. "Ok, I need a random integer from x and y." This helps give these functions the upper hand in terms of discoverability.
387
+
On the other end of the spectrum, we came into early agreement that `Collection.randomElement()` needs to return an optional in the case of an empty collection. If ranges were the primary spelling, then we would need to create exceptions for them to return non optionals. This would satisfy the general use design, but as we agreed that `.randomElement()` behaves more like `.first`, `.last`, `.min()`, and `.max()`. Because of this, `.randomElement()` has to return an optional to keep the consistent semantics. This justifies the static functions on the numeric types as the primary spelling as they can be the ones to return non optionals. These static functions are also the spelling for how developers think about going about random numbers. "Ok, I need a random integer from x and y." This helps give these functions the upper hand in terms of discoverability.
0 commit comments