extension Optional {
func ifSome<Result>(then closure: (Wrapped) throws -> Result) rethrows -> Optional {
if let wrapped = self { try _ = closure(wrapped) }
return self //for chaining to ifNone(then:)
}
func ifNone<Result>(then closure: () throws -> Result) rethrows {
if self == nil { try _ = closure() }
}
}
func doSomething(i: Int) { print(i) }
func doSomethingElse() { print("no value!") }
let i: Int? = 5
i.ifSome(then: doSomething)
.ifNone(then: doSomethingElse)
This is a contrived example of the usage, but it follows from your earlier point:
The same wrapping a long chain in a for
loop is a bit mesy, the same could be said for if
. The variable declaration is at the very start of the whole expression, before the chain, yet its usage is in the block at the very end, after the chain:
if let result = Something() // result defined all the way up here
.doSomething()
.map { $0.something }
.filter({ $0.isValid }) { // can't use trailing closure syntax on last line
use(result) //result used all the way down here
}
else {
handleNil()
}
compared to:
Something()
.doSomething()
.map { $0.something }
.filter{ $0.isValid } // can use trailing closure here
.ifSome(then: { result in use(result) }) // result declared close to where its used
// could even just be: .ifSome(then: use)
.ifNone(then: handleNil)
What would the forEach
equivalent be?
Something()
.doSomething()
.map { $0.something }
.filter{ $0.isValid }
.forEach(use)
.ifEmpty(the: handleNil) // Empty? I thought it was called Optional.none or nil!