apple / apple/swift-algorithms
One `reduce` overload to match `reductions` is missing.
- Dominant language
- Swift
- Stars
- 6.3k
- Forks
- 483
- PR merge metrics
- No merged PRs in 30d
Description
Four of the six `reductions` overloads correspond to a `reduce` overload from the standard library.
1.
* [reduce(_:_:)](https://developer.apple.com/documentation/swift/sequence/reduce(_:_:))
* [reductions(_:_:)](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/sequence/reductions(_:_:))
* [lazy version](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/lazysequenceprotocol/reductions(_:_:))
2.
* [reduce(into:_:)](https://developer.apple.com/documentation/swift/sequence/reduce(into:_:))
* [reductions(into:_:)](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/sequence/reductions(into:_:))
* [lazy version](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/lazysequenceprotocol/reductions(into:_:))
3.
* This `reduce` overload is missing.
* [reductions(_:)](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/sequence/reductions(_:))
* [lazy version](https://swiftpackageindex.com/apple/swift-algorithms/1.2.0/documentation/algorithms/swift/lazysequenceprotocol/reductions(_:))
The missing overload should return `nil`, for empty sequences.
```swift
@Test func reduce() {
let sequence = [1, 2, 3, 4]
#expect(sequence.reductions(+) == [1, 3, 6, 10])
#expect(sequence.reduce(+) == 10)
#expect(EmptyCollection().reductions(+) == [])
#expect(EmptyCollection().reduce(+) == nil)
}
```
Here's an implementation without typed throws:
```swift
public extension Sequence
@inlinable func reduce(
_ nextPartialResult: (Element, Element) throws -> Element
) rethrows -> Element? {
var iterator = makeIterator()
return try iterator.next().map { first in
try IteratorSequence(iterator).reduce(first, nextPartialResult)
}
}
}
```
Typed throws should be used, however.
```swift
@inlinable func reduce(
_ nextPartialResult: (Element, Element) throws(Error) -> Element
) throws(Error) -> Element? {
var iterator = makeIterator()
return try iterator.next().map { first throws(Error) in
try forceCastError(
to: Error.self,
IteratorSequence(iterator).reduce(first, nextPartialResult)
)
}
}
```
```swift
/// A mechanism to interface between untyped and typed errors.
///
/// When you know for certain that a value may only throw one type of error,
/// but that guarantee is not (or, due to compiler bugs, cannot be) represented in the type system,
/// you can use this to "convert" it to "typed throws".
/// - Parameters:
/// - errorType: The error type known for certain to be thrown by `value`.
/// - value: A value that might throw an `Error`.
/// - Important: A crash will occur if `value` throws any type but `Error`.
/// - Bug: [`errorType` must be explicitly provided](https://github.com/swiftlang/swift/issues/75674).
public func forceCastError(
to errorType: Error.Type = Error.self,
_ value: @autoclosure () throws -> Value
) throws(Error) -> Value {
do { return try value() }
catch { throw error as! Error }
}
```
Contributor guide
Research direction
Start by locating the existing Sequence.reductions overloads and the related reduce entry points, then compare their signatures and error-handling conventions. Add coverage to the shown reduce test for nonempty and empty sequences, including typed throws; done means the missing overload matches the reductions API and returns nil for an empty sequence.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- swift
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100