DiscriminatedUnion Protocol

How about something like F#'s active patterns, which are a way of defining custom mutually-exclusive conditions for pattern matching purposes? You could think of them as being "computed cases", a list of mutually exclusive cases whose value is determined by an associated block of code:

struct ErrorCode {
  // 0 if success, <0 if failure
  var value: Int

  // A computed case that lets you pattern match an ErrorCode
  case ok, error(code: Int) {
    assert(value <= 0)
    if value == 0 { return ok }
    return error(code: value)
  }
}

func handleError(code: ErrorCode) throws {
  switch code {
  case .ok: return
  case .error(let code): throw ErrorCodeError(code)
  }
}
17 Likes