Filtered optional-try expressions


With the try? operator, it’s easy to convert errors to optional values, which is useful for working with external code or when it’s unimportant what the error is. However, sometimes we want to handle some errors differently. To do this we need to use a do-catch statement. In the worst case, we need nested do statements.


The syntax of optional-try expressions is extended to allow specifying a filter on the error. If the error matches the filter, it is suppressed and the expression evaluates to nil. But if the error doesn’t match, it is propagated. Therefore, such expressions can only occur inside do blocks or throwing functions.

Syntax possibilities

Here, some syntax allows filtering by type only, and some by pattern.

  • try? is Problem f()
    Here, is Problem looks like a pattern. But if we allow any pattern, the syntax is ambiguous.
  • try? throws(Problem) f()
    Here, instead of Problem, we could allow patterns and write is Problem instead.
  • (Problem) try? f()
  • try? case Problem.specific f()
    This could allow a shorthand if the pattern is just is where case is elided
  • Problem.try? f()
    Possibly this could allow patterns, but that might be confusing to read or ambiguous
  • try? guard Problem f()
    Again, a pattern is possible
  • try? f() if is Problem or try? f() case Problem.specific

Most of these are probably ambiguous in some way and would require some careful precedence rules.

In many of these it could be a good idea to require braces, but in that case it becomes hardly shorter than a nested do statement, and it’d be unclear why the braces don’t contain statements, but expressions.

1 Like