Group Group Group Group Group Group Group Group Group

Possible errata for Chapter 1: Multi-paradigm: Functional, early-exit code block

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

If I use `reduce`'s throwing API, then we early exit on negative integers:
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:)

Although, I think the above is a harder to read than the following approach:
example("functional, early-exit") {
	let total = numbers
		.lazy
		.prefix { $0 >= 0 }
		.reduce(0, +)
	
	print(total)
}
1 Like

Very cool examples, @atfelix. When I wrote this section, I was imprecise. I didn’t actually check the compiler output and just theorized of a compiler that could, at least someday, deduce an early exit. But given that I actually do look at specific compiler output later in the chapter, it makes sense to check it. Let me mull over the best way to fix it. Thanks for this! (Approach 2 is lovely, BTW.)

1 Like