In Chapter 1, section Multi-paradigm, the function style early-exit code block states
It works, although the compiler needs to work hard to figure out that an early exit is possible.
I couldn’t get that code block (provided below) to early exit (using either debug or release mode). Am I missing something in my build settings or somewhere else? If not, I think the paragraph after the code block is an errata.
example("functional, early-exit") {
let total = numbers.reduce(
(accumulating: true, total: 0)
) { state, value in
if state.accumulating && value >= 0 {
return (accumulating: true, state.total + value)
}
else {
return (accumulating: false, state.total)
}
}
.total
print(total)
}
Here are two alternative functional styles that do early exit
Approach 1: reduce
’s throwing API
try example("functional, early-exit") {
struct SumError: Error {
let sum: Int
}
let total: Result<Int, Never> = Result {
try numbers.reduce(0) { (accumulator, value) throws -> Int in
if value >= 0 {
return accumulator + value
}
else {
throw SumError(sum: accumulator)
}
}
}
.flatMapError { error in
guard let error = error as? SumError else { fatalError() }
return .success(error.sum)
}
try print(total.get())
}
Approach 2: prefix(while:)
example("functional, early-exit") {
let total = numbers
.lazy
.prefix { $0 >= 0 }
.reduce(0, +)
print(total)
}