Skip to content

Commit 22ea738

Browse files
committed
Update API to reflect mailing list discussions
Remove unnecessary import Make sure not to return upperBound on Range Use SecRandomCopyBytes on older macOS
1 parent 310e4e1 commit 22ea738

11 files changed

+323
-196
lines changed

stdlib/public/SwiftShims/LibcShims.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ _swift_stdlib_cxx11_mt19937_uniform(__swift_uint32_t upper_bound);
9696
SWIFT_RUNTIME_STDLIB_INTERFACE
9797
void _swift_stdlib_random(void *buf,
9898
__swift_ssize_t nbytes,
99-
__swift_uint32_t debugFlags);
99+
__swift_uint32_t debug_flags);
100100

101101
// Math library functions
102102
static inline SWIFT_ALWAYS_INLINE

stdlib/public/core/Bool.swift

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,14 @@ public struct Bool : Randomizable {
8888
self = value
8989
}
9090

91+
/// Returns a random Boolean
92+
///
93+
/// - Parameter generator: The random number generator to use when getting a
94+
/// random Boolean.
95+
/// - Returns: A random Boolean.
9196
@_inlineable
92-
public static func random(using generator: RandomGenerator) -> Bool {
93-
let random = generator.next(Int8.self, upperBound: 2)
97+
public static func random<T: RandomNumberGenerator>(using generator: T) -> Bool {
98+
let random = Int8.random(using: generator)
9499
return self.init(Builtin.trunc_Int8_Int1(random._value))
95100
}
96101
}

stdlib/public/core/Collection.swift

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -781,14 +781,39 @@ public protocol Collection : Sequence
781781
/// `endIndex`.
782782
func formIndex(after i: inout Index)
783783

784-
/// Returns a shuffled version of this collection.
784+
/// Returns a random element from this collection.
785785
///
786-
/// - Parameter generator: The random number generator to use when shuffling
787-
/// the collection. This parameter is not needed as the default implementation
788-
/// of `Collection` uses the default random source in the standard library.
789-
/// - Returns: A new array containing a shuffled version of this collection's
790-
/// elements.
791-
func shuffled(using generator: RandomGenerator) -> [Element]
786+
/// A good example of this is getting a random number from 1 to 10:
787+
///
788+
/// let randomToTen = (1 ... 10).random
789+
///
790+
/// If the collection is empty, the value of this function is `nil`.
791+
///
792+
/// let numbers = [10, 20, 30, 40, 50]
793+
/// if let randomNumber = numbers.random {
794+
/// print(randomNumber)
795+
/// }
796+
/// // Could print "20"
797+
var random: Element? { get }
798+
799+
/// Returns a random element from this collection.
800+
///
801+
/// - Parameter generator: The random number generator to use when getting
802+
/// a random element.
803+
/// - Returns: A random element from this collection.
804+
///
805+
/// A good example of this is getting a random number from 1 to 10:
806+
///
807+
/// let randomToTen = (1 ... 10).random
808+
///
809+
/// If the collection is empty, the value of this function is `nil`.
810+
///
811+
/// let numbers = [10, 20, 30, 40, 50]
812+
/// if let randomNumber = numbers.random {
813+
/// print(randomNumber)
814+
/// }
815+
/// // Could print "20"
816+
func random<T: RandomNumberGenerator>(using generator: T) -> Element?
792817
}
793818

794819
/// Default implementation for forward collections.
@@ -1000,20 +1025,52 @@ extension Collection {
10001025
return count
10011026
}
10021027

1003-
/// Returns a shuffled version of this collection.
1028+
/// Returns a random element from this collection.
10041029
///
1005-
/// - Parameter generator: The random number generator to use when shuffling
1006-
/// the collection. This parameter is not needed as the default implementation
1007-
/// of `Collection` uses the default random source in the standard library.
1008-
/// - Returns: A new array containing a shuffled version of this collection's
1009-
/// elements.
1030+
/// This uses the default random number generator provided by the standard library.
1031+
/// A good example of this is getting a random number from 1 to 10:
1032+
///
1033+
/// let randomToTen = (1 ... 10).random
1034+
///
1035+
/// If the collection is empty, the value of this function is `nil`.
1036+
///
1037+
/// let numbers = [10, 20, 30, 40, 50]
1038+
/// if let randomNumber = numbers.random {
1039+
/// print(randomNumber)
1040+
/// }
1041+
/// // Could print "20"
10101042
@_inlineable
1011-
public func shuffled(
1012-
using generator: RandomGenerator = Random.default
1013-
) -> [Element] {
1014-
var arr = Array(self)
1015-
arr.shuffle(using: generator)
1016-
return arr
1043+
public var random: Element? {
1044+
return self.random(using: Random.default)
1045+
}
1046+
1047+
/// Returns a random element from this collection.
1048+
///
1049+
/// - Parameter generator: The random number generator to use when getting
1050+
/// a random element.
1051+
/// - Returns: A random element this collection.
1052+
///
1053+
/// A good example of this is getting a random number from 1 to 10:
1054+
///
1055+
/// let randomToTen = (1 ... 10).random
1056+
///
1057+
/// If the collection is empty, the value of this function is `nil`.
1058+
///
1059+
/// let numbers = [10, 20, 30, 40, 50]
1060+
/// if let randomNumber = numbers.random {
1061+
/// print(randomNumber)
1062+
/// }
1063+
/// // Could print "20"
1064+
@_inlineable
1065+
public func random<T: RandomNumberGenerator>(using generator: T) -> Element? {
1066+
guard !isEmpty else { return nil }
1067+
var random = generator.next(upperBound: UInt(self.count))
1068+
let index = self.index(
1069+
self.startIndex,
1070+
offsetBy: IndexDistance(random),
1071+
limitedBy: self.endIndex
1072+
)
1073+
return self[index!]
10171074
}
10181075

10191076
/// Do not use this method directly; call advanced(by: n) instead.

stdlib/public/core/CollectionAlgorithms.swift.gyb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,81 @@ extension MutableCollection where Self : BidirectionalCollection {
211211
}
212212
}
213213

214+
//===----------------------------------------------------------------------===//
215+
// shuffled()
216+
//===----------------------------------------------------------------------===//
217+
218+
% for Self in ['Sequence', 'MutableCollection']:
219+
220+
% sequenceKind = 'sequence' if 'Sequence' in Self else 'collection'
221+
222+
extension ${Self} {
223+
/// Returns the elements of the ${sequenceKind}, shuffled.
224+
///
225+
/// - Returns: A shuffled array of this ${sequenceKind}'s elements.
226+
///
227+
/// This uses the default random number generator provided by the standard library.
228+
@_inlineable
229+
public func shuffled() -> [Element] {
230+
return self.shuffled(using: Random.default)
231+
}
232+
233+
/// Returns the elements of the ${sequenceKind}, shuffled.
234+
///
235+
/// - Parameter generator: The random number generator to use when shuffling
236+
/// the ${sequenceKind}.
237+
/// - Returns: A shuffled array of this ${sequenceKind}'s elements.
238+
@_inlineable
239+
public func shuffled<T: RandomNumberGenerator>(
240+
using generator: T
241+
) -> [Element] {
242+
var result = ContiguousArray(self)
243+
result.shuffle(using: generator)
244+
return Array(result)
245+
}
246+
}
247+
248+
% end
249+
250+
extension MutableCollection {
251+
/// Shuffles the collection in place.
252+
///
253+
/// This uses the default random number generator provided by the standard library.
254+
@_inlineable
255+
public mutating func shuffle() {
256+
self.shuffle(using: Random.default)
257+
}
258+
259+
/// Shuffles the collection in place.
260+
///
261+
/// - Parameter generator: The random number generator to use when shuffling
262+
/// the collection.
263+
@_inlineable
264+
public mutating func shuffle<T: RandomNumberGenerator>(
265+
using generator: T
266+
) {
267+
guard count > 1 else { return }
268+
var amount = count
269+
while amount > 1 {
270+
var random = generator.next(upperBound: UInt(count))
271+
guard amount != random else { continue }
272+
amount -= 1
273+
swapAt(
274+
index(
275+
startIndex,
276+
offsetBy: IndexDistance(amount),
277+
limitedBy: endIndex
278+
)!,
279+
index(
280+
startIndex,
281+
offsetBy: IndexDistance(random),
282+
limitedBy: endIndex
283+
)!
284+
)
285+
}
286+
}
287+
}
288+
214289
//===----------------------------------------------------------------------===//
215290
// sorted()
216291
//===----------------------------------------------------------------------===//

stdlib/public/core/FloatingPoint.swift.gyb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2108,7 +2108,7 @@ extension BinaryFloatingPoint {
21082108
///
21092109
/// The range of this random floating point is from 0 to 1 inclusive
21102110
@_inlineable
2111-
public static func random(using generator: RandomGenerator) -> Self {
2111+
public static func random<T: RandomNumberGenerator>(using generator: T) -> Self {
21122112
let random = generator.next(UInt64.self)
21132113
return Self(random) / Self(UInt64.max)
21142114
}

stdlib/public/core/Integers.swift.gyb

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2606,7 +2606,33 @@ extension FixedWidthInteger {
26062606
/// The range of this random integer is from the integer's min to the integer's
26072607
/// max.
26082608
@_inlineable
2609-
public static func random(using generator: RandomGenerator) -> Self {
2609+
public static func random<T: RandomNumberGenerator>(using generator: T) -> Self {
2610+
switch bitWidth {
2611+
case 8:
2612+
return Self.init(truncatingIfNeeded: generator.next(UInt8.self))
2613+
case 16:
2614+
return Self.init(truncatingIfNeeded: generator.next(UInt16.self))
2615+
case 32:
2616+
return Self.init(truncatingIfNeeded: generator.next(UInt32.self))
2617+
case 64:
2618+
return Self.init(truncatingIfNeeded: generator.next(UInt64.self))
2619+
default:
2620+
return Self.init(truncatingIfNeeded: generator.next())
2621+
}
2622+
}
2623+
}
2624+
2625+
extension FixedWidthInteger where Self: UnsignedInteger {
2626+
/// Returns a random representation of this integer.
2627+
///
2628+
/// - Parameter generator: The random number generator to use when getting
2629+
/// the random integer
2630+
/// - Returns: A random representation of this integer conforming to `Randomizable`
2631+
///
2632+
/// The range of this random integer is from the integer's min to the integer's
2633+
/// max.
2634+
@_inlineable
2635+
public static func random<T: RandomNumberGenerator>(using generator: T) -> Self {
26102636
return generator.next(Self.self)
26112637
}
26122638
}

stdlib/public/core/MutableCollection.swift

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,6 @@ public protocol MutableCollection : Collection
159159
by belongsInSecondPartition: (Element) throws -> Bool
160160
) rethrows -> Index
161161

162-
/// Shuffles the current collection
163-
///
164-
/// - Parameter generator: The random number generator to use when shuffling
165-
/// the collection. This parameter is not needed as the default implementation
166-
/// of `Collection` uses the default random source in the standard library.
167-
mutating func shuffle(using generator: RandomGenerator)
168-
169162
/// Exchanges the values at the specified indices of the collection.
170163
///
171164
/// Both parameters must be valid indices of the collection and not
@@ -234,37 +227,6 @@ extension MutableCollection {
234227
}
235228
}
236229

237-
/// Shuffles the current collection
238-
///
239-
/// - Parameter generator: The random number generator to use when shuffling
240-
/// the collection. This parameter is not needed as the default implementation
241-
/// of `Collection` uses the default random source in the standard library.
242-
@_inlineable
243-
public mutating func shuffle(
244-
using generator: RandomGenerator = Random.default
245-
) {
246-
guard count > 1 else { return }
247-
var amount = count
248-
while amount > 1 {
249-
var random = generator.next(Int.self, upperBound: Int(count))
250-
if random < 0 { random *= -1 }
251-
guard amount != random else { continue }
252-
amount -= 1
253-
swapAt(
254-
index(
255-
startIndex,
256-
offsetBy: IndexDistance(amount),
257-
limitedBy: endIndex
258-
)!,
259-
index(
260-
startIndex,
261-
offsetBy: IndexDistance(random),
262-
limitedBy: endIndex
263-
)!
264-
)
265-
}
266-
}
267-
268230
/// Exchanges the values at the specified indices of the collection.
269231
///
270232
/// Both parameters must be valid indices of the collection that are not

0 commit comments

Comments
 (0)