IssueRaiser

First-class, functional-style `Result<E, T>` types with built-in operators

## Proposal With sealed classes and exhaustive pattern matching, I think we've hit a natural time to add first-class result types to the language, or at least the first-party libraries (the ones published by `dart.dev`): ```dart sealed class Result<E, T> { R match<R>({ required R Function(E) onError, required R Function(T) onValue, }) => switch (this) { Failure(error: final error) => onError(error), Success(value: final value) => onValue(value), }; T onError(T Function(E) onError) => switch (this) { Failure(error: final error) => onError(error), Success(value: final value) => value, }; T assertErrors() => switch (this) { Failure(error: final error) => throw StateError("Result type had an error value: $error"), Success(value: final value) => value, }; } class Failure<E, T> extends Result<E, T> { final E error; Failure(this.error); } class Success<E, T> extends Result<E, T> { final T value; Success(this.value); } ``` Usage would look like: ```dart Result<String, int> getNum() => Random().nextBool() ? Success(123) : Failure("Oops!"); void main() { // Simply handle each case getNum().match( onError: (reason) => print("Couldn't get number because $reason"), onValue: (value) => print("Got number! ${value + 1}"), ); // Use a value based on the presence of an error final number = getNum().match( onError: (error) => 0, onValue: (value) => value + 1, ); // or if you just want to

Posted by Levi-Lesches on Dec 8, 2023, 8:47 AM

Tags

Related issues

Raise real-world problems, find people facing the same issue, and discuss solutions.2,000 issues0 comments

github (Other)

First-class, functional-style `Result<E, T>` types with built-in operators

Levi-LeschesDec 8, 2023, 8:47 AM

## Proposal With sealed classes and exhaustive pattern matching, I think we've hit a natural time to add first-class result types to the language, or at least the first-party libraries (the ones published by `dart.dev`): ```dart sealed class Result<E, T> { R match<R>({ required R Function(E) onError, required R Function(T) onValue, }) => switch (this) { Failure(error: final error) => onError(error), Success(value: final value) => onValue(value), }; T onError(T Function(E) onError) => switch (this) { Failure(error: final error) => onError(error), Success(value: final value) => value, }; T assertErrors() => switch (this) { Failure(error: final error) => throw StateError("Result type had an error value: $error"), Success(value: final value) => value, }; } class Failure<E, T> extends Result<E, T> { final E error; Failure(this.error); } class Success<E, T> extends Result<E, T> { final T value; Success(this.value); } ``` Usage would look like: ```dart Result<String, int> getNum() => Random().nextBool() ? Success(123) : Failure("Oops!"); void main() { // Simply handle each case getNum().match( onError: (reason) => print("Couldn't get number because $reason"), onValue: (value) => print("Got number! ${value + 1}"), ); // Use a value based on the presence of an error final number = getNum().match( onError: (error) => 0, onValue: (value) => value + 1, ); // or if you just want to

Comments (0)

No comments yet. Start the discussion.

Comment on this issue