Skip to content

Result<TSuccess, TFailure> generator #648

@bernardnormier

Description

@bernardnormier

This is a proposal to add a Result<TSuccess, TFailure> as a kind of generator for enum with associated values.

Prerequisite: enum with associated values as described in #30 (comment)

Result<TSuccess, TFailure> is an enum with 2 enumerators (Success & Failure). TSuccess can be a single type or a tuple while TFailure must be a single type.

Result<(x: int32, y: string, tag(1) z: string?), MyError> is a short-hand for:

// a checked enum
enum Result<(x: int32, y: string), MyError> { // pseudo Slice since this is not a valid Slice identifier
    Success(x: int32, y: string, tag(1) z: string?) // the success tuple as-is
    Failure(value: MyError) // MyError can be any type or typealias, but not a tuple; can't be optional, like typealias
}

Result<tag(1) string?, int32> is a short-hand for:

// a checked enum
enum Result<tag(1) string?, int32> { // pseudo Slice since this is not a valid Slice identifier
    Success(tag(1) value: string?)
    Failure(value: int32)
}

Then, you can use Result<TSuccess, TFailure> anywhere you can use a type: as a field, as an operation parameter, and more commonly, as a operation return type:

interface Greeter {
    greet(name: string) -> Result<string, GreeterError>
}

struct GreeterError {
    message: string
    errorCode: int32
}

At the IceRPC level, this return value is a StatusCode=Success, even if it holds a GreeterError.

stream parameter

The Result success tuple is fed into the Success enumerator's associated value and can't include a stream. If you want a stream parameter, it has to be separate:

interface Example {
    op() -> (result: Result<string, string>, stream: Sequence<uint8>)
    op() -> stream Result<string, string>
}

Comparison with previous Result proposal

In #3571, Result is a special notation that maps (with IceRPC) to StatusCode=Success and StatusCode=ApplicationError, and takes advantage of the error message carried by the icerpc StatusCode=ApplicationError response.

One advantage of the #3571 proposal is:

op() -> string
op() -> Result<string, SomeError>

are "on-the-wire" compatible. That's no longer the case with the new proposal, where Result is a short-hand for an enum.

Language mapping

In Rust and Swift, we would naturally map Result to the native Result type.

In C#, we could create our own generic struct or class. We need map enum-with-associated-value in any case, so we can create a similar looking Result generic. An alternative would be to reuse a third-party Result type.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions