Comparing result of `try?`

I want to check whether the result of a throwing function is a specific value, while suppressing errors:

enum E {
  case foo, bar
}

func baz() throws -> E {
  // ...
}

if try? baz() == .foo {
  // ...
}

However, this gives the error

optional type 'Bool?' cannot be used as a boolean; test for '!= nil' instead

My initial thought is that it's parsing this as try? (baz() == .foo) rather than (try? baz()) == .foo. Rather than adding parentheses, I flip the operands, to make the misparse impossible:

if .foo == try? baz() {
  // ...
}

This results in a different error:

'try?' cannot appear to the right of a non-assignment operator

I can understand this restriction for some operators, but why ==/!=? Why are the seemingly superfluous parentheses necessary?

1 Like

You need enum testing syntax for this particular case where E is an enum. I personally have always found it a little awkward to read, but it's the canonical form.

if case .foo = try? baz() {
  // ...
}

Alternatively, this will work with any throwing return, not just enums

if let x = try? baz(), x == .foo {
  // ...
}
2 Likes

Strictly speaking I don’t need if case/if let — using parens like (try? baz()) == .foo works fine — but it is good to know that’s another option in some cases.

True, just meant in terms of idiomatic Swift and how it wants enum cases to be handled in this form! Would agree that parens in the conditional can be rather awkward to read. Practically speaking there should be no distinction in terms of performance between the paren version and the case or let ones, though.

1 Like