Result<Success, Failure: Error> is defined as enum Result { case success(Success); case failure(Failure) } — an entirely ordinary enum, storable, passable, and usable anywhere a value is needed, unlike a thrown error which must be caught immediately at the call site. Conforming a custom type to Sequence (by implementing makeIterator(), which returns something conforming to IteratorProtocol with a next() method) makes it directly usable in a for-in loop and grants it the full range of sequence operations — map, filter, contains, and more — automatically, entirely from implementing those two small requirements.
Result: a storable alternative to throws
Unlike a thrown error, which must be handled immediately with try/catch, a Result value can be stored, passed around, and handled whenever is actually convenient — genuinely useful for completion handlers or anywhere deferred error handling makes more sense.
enum ValidationError: Error {
case tooShort
}
func validate(_ input: String) -> Result<String, ValidationError> {
if input.count < 3 {
return .failure(.tooShort)
}
return .success(input)
}
switch validate("hi") {
case .success(let value):
print("Valid: \(value)")
case .failure(let error):
print("Invalid: \(error)")
}Sequence and IteratorProtocol: powering for-in on custom types
Implementing exactly these two small pieces — an iterator with next(), and makeIterator() to produce one — is all that's needed for Countdown to work directly in a for-in loop, and to gain the whole standard library of sequence operations automatically.
struct Countdown: Sequence {
let start: Int
func makeIterator() -> CountdownIterator {
return CountdownIterator(current: start)
}
}
struct CountdownIterator: IteratorProtocol {
var current: Int
mutating func next() -> Int? {
guard current > 0 else { return nil }
defer { current -= 1 }
return current
}
}
for n in Countdown(start: 3) {
print(n) // 3, 2, 1
}The custom sequence gets map/filter for free
Once Sequence conformance exists, the standard library's full set of sequence operations becomes available automatically — no additional code needed for map, filter, or any of the rest.
let doubled = Countdown(start: 3).map { $0 * 2 }
print(doubled) // [6, 4, 2] — map worked automatically, no extra code written