Skip to content

Commit 04b5174

Browse files
committed
stdlib: Remove Collection.randomElement customization point.
As proposed and accepted in amendment swiftlang/swift-evolution#863. rdar://problem/41067949
1 parent e7ee53b commit 04b5174

File tree

2 files changed

+30
-107
lines changed

2 files changed

+30
-107
lines changed

stdlib/public/core/Collection.swift

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -796,25 +796,6 @@ public protocol Collection: Sequence where SubSequence: Collection {
796796
/// - Parameter i: A valid index of the collection. `i` must be less than
797797
/// `endIndex`.
798798
func formIndex(after i: inout Index)
799-
800-
/// Returns a random element of the collection, using the given generator as
801-
/// a source for randomness.
802-
///
803-
/// You use this method to select a random element from a collection when you
804-
/// are using a custom random number generator. For example, call
805-
/// `randomElement(using:)` to select a random element from an array of names.
806-
///
807-
/// let names = ["Zoey", "Chloe", "Amani", "Amaia"]
808-
/// let randomName = names.randomElement(using: &myGenerator)!
809-
/// // randomName == "Amani"
810-
///
811-
/// - Parameter generator: The random number generator to use when choosing
812-
/// a random element.
813-
/// - Returns: A random element from the collection. If the collection is
814-
/// empty, the method returns `nil`.
815-
__consuming func randomElement<T: RandomNumberGenerator>(
816-
using generator: inout T
817-
) -> Element?
818799
}
819800

820801
/// Default implementation for forward collections.

stdlib/public/core/Integers.swift.gyb

Lines changed: 30 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2535,93 +2535,6 @@ ${assignmentOperatorComment(x.operator, False)}
25352535
% for Range in ['Range', 'ClosedRange']:
25362536
% exampleRange = '1..<100' if Range == 'Range' else '1...100'
25372537
2538-
extension ${Range}
2539-
where Bound: FixedWidthInteger, Bound.Stride : SignedInteger,
2540-
Bound.Magnitude: UnsignedInteger
2541-
{
2542-
2543-
/// Returns a random element of the range, using the given generator as
2544-
/// a source for randomness.
2545-
///
2546-
/// You can use this method to select a random element of a range when you
2547-
/// are using a custom random number generator. If you're generating a random
2548-
/// number, in most cases, you should prefer using the `random(in:using:)`
2549-
/// static method of the desired numeric type. That static method is available
2550-
/// for both integer and floating point types, and returns a non-optional
2551-
/// value.
2552-
///
2553-
/// - Parameter generator: The random number generator to use when choosing
2554-
/// a random element.
2555-
/// - Returns: A random element of the range.
2556-
% if 'Closed' not in Range:
2557-
/// If the range is empty, the method returns `nil`.
2558-
% else:
2559-
/// This method never returns `nil`.
2560-
% end
2561-
@inlinable
2562-
public func randomElement<T: RandomNumberGenerator>(
2563-
using generator: inout T
2564-
) -> Element? {
2565-
guard !isEmpty else {
2566-
return nil
2567-
}
2568-
// Compute delta, the distance between the lower and upper bounds. This
2569-
// value may not representable by the type Bound if Bound is signed, but
2570-
// is always representable as Bound.Magnitude.
2571-
% if 'Closed' in Range:
2572-
var delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
2573-
% else:
2574-
let delta = Bound.Magnitude(truncatingIfNeeded: upperBound &- lowerBound)
2575-
% end
2576-
% if 'Closed' in Range:
2577-
// Subtle edge case: if the range is the whole set of representable values,
2578-
// then adding one to delta to account for a closed range will overflow.
2579-
// If we used &+ instead, the result would be zero, which isn't helpful,
2580-
// so we actually need to handle this case separately.
2581-
if delta == Bound.Magnitude.max {
2582-
return Bound(truncatingIfNeeded: generator.next() as Bound.Magnitude)
2583-
}
2584-
// Need to widen delta to account for the right-endpoint of a closed range.
2585-
delta += 1
2586-
% end
2587-
// The mathematical result we want is lowerBound plus a random value in
2588-
// 0 ..< delta. We need to be slightly careful about how we do this
2589-
// arithmetic; the Bound type cannot generally represent the random value,
2590-
// so we use a wrapping addition on Bound.Magnitude. This will often
2591-
// overflow, but produces the correct bit pattern for the result when
2592-
// converted back to Bound.
2593-
return Bound(truncatingIfNeeded:
2594-
Bound.Magnitude(truncatingIfNeeded: lowerBound) &+
2595-
generator.next(upperBound: delta)
2596-
)
2597-
}
2598-
2599-
/// Returns a random element of the range, using the given generator as
2600-
/// a source for randomness.
2601-
///
2602-
/// You can use this method to select a random element of a range when you
2603-
/// are using a custom random number generator. If you're generating a random
2604-
/// number, in most cases, you should prefer using the `random(in:)`
2605-
/// static method of the desired numeric type. That static method is available
2606-
/// for both integer and floating point types, and returns a non-optional
2607-
/// value.
2608-
///
2609-
/// This method uses the default random generator, `Random.default`. Calling
2610-
/// `(${exampleRange}).randomElement()` is equivalent to calling
2611-
/// `(${exampleRange}).randomElement(using: &Random.default)`.
2612-
///
2613-
/// - Returns: A random element of the range.
2614-
% if 'Closed' not in Range:
2615-
/// If the range is empty, the method returns `nil`.
2616-
% else:
2617-
/// This method never returns `nil`.
2618-
% end
2619-
@inlinable
2620-
public func randomElement() -> Element? {
2621-
return randomElement(using: &Random.default)
2622-
}
2623-
}
2624-
26252538
extension FixedWidthInteger
26262539
where Self.Stride : SignedInteger,
26272540
Self.Magnitude : UnsignedInteger {
@@ -2657,7 +2570,36 @@ where Self.Stride : SignedInteger,
26572570
!range.isEmpty,
26582571
"Can't get random value with an empty range"
26592572
)
2660-
return range.randomElement(using: &generator)!
2573+
2574+
// Compute delta, the distance between the lower and upper bounds. This
2575+
// value may not representable by the type Bound if Bound is signed, but
2576+
// is always representable as Bound.Magnitude.
2577+
% if 'Closed' in Range:
2578+
var delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
2579+
% else:
2580+
let delta = Magnitude(truncatingIfNeeded: range.upperBound &- range.lowerBound)
2581+
% end
2582+
% if 'Closed' in Range:
2583+
// Subtle edge case: if the range is the whole set of representable values,
2584+
// then adding one to delta to account for a closed range will overflow.
2585+
// If we used &+ instead, the result would be zero, which isn't helpful,
2586+
// so we actually need to handle this case separately.
2587+
if delta == Magnitude.max {
2588+
return Self(truncatingIfNeeded: generator.next() as Magnitude)
2589+
}
2590+
// Need to widen delta to account for the right-endpoint of a closed range.
2591+
delta += 1
2592+
% end
2593+
// The mathematical result we want is lowerBound plus a random value in
2594+
// 0 ..< delta. We need to be slightly careful about how we do this
2595+
// arithmetic; the Bound type cannot generally represent the random value,
2596+
// so we use a wrapping addition on Bound.Magnitude. This will often
2597+
// overflow, but produces the correct bit pattern for the result when
2598+
// converted back to Bound.
2599+
return Self(truncatingIfNeeded:
2600+
Magnitude(truncatingIfNeeded: range.lowerBound) &+
2601+
generator.next(upperBound: delta)
2602+
)
26612603
}
26622604
26632605
/// Returns a random value within the specified range.

0 commit comments

Comments
 (0)