If let a = b, a.something () else
I have a piece of code that works, but I'm curious if there is a cleaner way to do the same. I haven't seen anything like it yet.
Logic I want to achieve
-
error
-nil
or is notSpecialError
-
error
non-nil
BUT.foo()
returnsfalse
code
enum SpecialError: Error {
func foo() -> Bool
}
let error: Error? // Some optional Error is passed in
if let myError = error as? SpecialError, myError.foo() {
// Don't care about this case
} else {
// This is the case I'm interested in
bar()
}
I'm curious if there is a better way to accomplish this logic if let else
.
source to share
The condition you want is an expression, when the expression (error as? SpecialError)?.foo()
evaluates to either:
-
nil
, in which caseerror
it is notSpecialError
, or isnil
. -
false
, in this caseerror
isSpecialError
butfoo()
returnedfalse
.
In your case, one way to express this is by taking advantage of the fact that equality operators are overloaded for options and say:
if (error as? SpecialError)?.foo() != true {
bar()
}
Since we are using an overload !=
that compares options true
will advance to Bool?
, so we check what is (error as? SpecialError)?.foo()
not .some(true)
, which in this case is equivalent to checking whether it is .some(false)
or .none
.
source to share
I may be wrong, but it seems like nothing is happening in the first branch of the instruction if
, and you want to shorten it to the second part? In this case, this should work for you:
if !((error as? SpecialError)?.foo() ?? false) {
bar()
}
This is accomplished bar()
when:
1. error
equal to nil 2. error
does not SpecialError
3. foo()
returns false
source to share
I think your code is hard to read, and John Montgomery's code is even harder to read, and I predict it will be difficult to maintain: Imagine another developer looking at this code a year later and asking you what it does, or what even worse, the developer cannot ask you since you are no longer available. Imagine looking at this code even after a couple of months.
if let myError = error as? SpecialError, myError.foo()
confused, perhaps too smart. It contains too much logic to be read for a long time by the development team.
Your first block can just check if myError is nil
The second block can just check if myError is of type SpecialError
//you could use a guard statement here
if myError == nil {
return;
}
if let myError = error as? SpecialError {
//ok myError is type SpecialError it has a foo method I can call
if(myError.foo()) {
//do something
} else {
//do something else
}
} else { //myError not type SpecialError and is not nil
// This is the case I'm interested in
bar()
}
source to share