Skip to content

Commit 4ff7d60

Browse files
authored
Merge pull request #863 from jckarter/0202-amendment-remove-randomElement-requirement
SE-0202 amendment: Remove `Collection.randomElement` requirement.
2 parents 74d62ec + 68257da commit 4ff7d60

File tree

1 file changed

+10
-56
lines changed

1 file changed

+10
-56
lines changed

proposals/0202-random-unification.md

Lines changed: 10 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ let randomBool2 = Bool.random(using: &myCustomRandomNumberGenerator)
131131

132132
#### Random Element
133133

134-
For `Collection` we add a random method with default implementation for collections to get a random element.
134+
For `Collection` we add an extension method for collections to get a random element.
135135

136136
`Collection` example:
137137
```swift
@@ -143,6 +143,13 @@ print(greetings.randomElement()!) // This returns an Optional
143143
print(greetings.randomElement(using: &myCustomRandomNumberGenerator)!) // This returns an Optional
144144
```
145145

146+
Note that some types make it easy to form collections with more elements than
147+
can be represented as an `Int`, such as the range `Int.min...Int.max`, and
148+
`randomElement` will likely trap on such collections. However, such ranges
149+
are likely to trap when used with almost any collection API, and the
150+
`random(in:)` method on `FixedWidthInteger` can be used for this purpose
151+
instead.
152+
146153
#### Shuffle API
147154

148155
As a result of adding the random API, it only makes sense to utilize that power to fuel the shuffle methods. We extend `MutableCollection` to add a method to shuffle the collection itself, and extend `Sequence` to add a method to return a shuffled version of itself in a new array. Example:
@@ -199,14 +206,6 @@ public struct Random : RandomNumberGenerator {
199206
public mutating func next<T: FixedWidthInteger & UnsignedInteger>() -> T
200207
}
201208

202-
public protocol Collection {
203-
// Returns a random element from the collection
204-
func randomElement<T: RandomNumberGenerator>(
205-
using generator: inout T
206-
) -> Element?
207-
}
208-
209-
// Default implementation
210209
extension Collection {
211210
// Returns a random element from the collection
212211
// Can return nil if isEmpty is true
@@ -220,52 +219,12 @@ extension Collection {
220219
}
221220
}
222221

223-
// We have to add this extension to support syntax like (Int.min ..< Int.max).random()
224-
// That fails because Collection's implementation utilizes the count property and
225-
// from Int.min to Int.max, an Int overflows with that big of a value.
226-
extension Range
227-
where Bound : FixedWidthInteger,
228-
Bound.Stride : SignedInteger,
229-
Bound.Magnitude : UnsignedInteger {
230-
// Returns a random element within lowerBound and upperBound
231-
// Can return nil if lowerBound == upperBound
232-
public func randomElement<T: RandomNumberGenerator>(
233-
using generator: inout T
234-
) -> Element?
235-
236-
/// Uses the standard library's default RNG
237-
public func randomElement() -> Element? {
238-
return randomElement(using: &Random.default)
239-
}
240-
}
241-
242-
// We have to add this extension to support syntax like (Int.min ... Int.max).random()
243-
// That fails because Collection's implementation utilizes the count property and
244-
// from Int.min to Int.max, an Int overflows with that big of a value.
245-
extension ClosedRange
246-
where Bound : FixedWidthInteger,
247-
Bound.Stide : SignedInteger,
248-
Bound.Magnitude : UnsignedInteger {
249-
// Returns a random element within lowerBound and upperBound
250-
public func randomElement<T: RandomNumberGenerator>(
251-
using generator: inout T
252-
) -> Element?
253-
254-
/// Uses the standard library's default RNG
255-
public func randomElement() -> Element? {
256-
return random(using: &Random.default)
257-
}
258-
}
259-
260222
// Enables developers to use things like Int.random(in: 5 ..< 12) which does not use modulo bias.
261-
// This differs from things like (5 ..< 12).randomElement() because those ranges return an Optional, whereas
262-
// this returns a non-optional. Ranges get the benefit of using random, but this is the preferred
263-
// method as it provides a cleaner API to users and clearly expresses the operation.
264223
// It is worth noting that any empty range entered here will abort the program.
265224
// We do this to preserve a general use case design that the core team expressed.
266225
// For those that are that unsure whether or not their range is empty or not,
267-
// they can simply call random from the range itself to produce an Optional, or if/guard check
268-
// whether or not the range is empty beforehand, then use these functions.
226+
// they can if/guard check whether or not the range is empty beforehand, then
227+
// use these functions.
269228
extension FixedWidthInteger
270229
where Self.Stride : SignedInteger,
271230
Self.Magnitude : UnsignedInteger {
@@ -292,9 +251,6 @@ where Self.Stride : SignedInteger,
292251
}
293252

294253
// Enables developers to use things like Double.random(in: 5 ..< 12) which does not use modulo bias.
295-
// This differs from things like (5.0 ..< 12.0).randomElement() because those ranges return an Optional, whereas
296-
// this returns a non-optional. Ranges get the benefit of using random, but this is the preferred
297-
// method as it provides a cleaner API to users and clearly expresses the operation.
298254
// It is worth noting that any empty range entered here will abort the program.
299255
// We do this to preserve a general use case design that the core team expressed.
300256
// For those that are that unsure whether or not their range is empty or not,
@@ -393,8 +349,6 @@ In a world where this did return an error to Swift, it would require types like
393349

394350
```swift
395351
let randomDice = Int.random(in: 1 ... 6)!
396-
// would be equivalent to
397-
// let randomDice = (1 ... 6).randomElement()!
398352
```
399353

400354
"I just want a random dice roll, what is this ! the compiler is telling me to add?"

0 commit comments

Comments
 (0)