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
- struct's lifetime requirements can be bypassed via covariant field assignment
- Proposal to Reorganize the Moderation Team and Review Moderation Policies
- Progressive FPS degradation appears to be related to dota2.com — blocking the domain prevents the performance loss
- proposal: container/...: generic collection types
- Better Custom Endpoint BYOK
- A concrete policy for backward compatibility until Godot 5.0
Raise real-world problems, find people facing the same issue, and discuss solutions.2,000 issues0 comments
github (Other)
struct's lifetime requirements can be bypassed via covariant field assignment
Proposal to Reorganize the Moderation Team and Review Moderation Policies
Progressive FPS degradation appears to be related to dota2.com — blocking the domain prevents the performance loss
proposal: container/...: generic collection types
Better Custom Endpoint BYOK
A concrete policy for backward compatibility until Godot 5.0
New MTP models not supported
Tracking: 429 / Capacity Issues
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
Comments (0)
No comments yet. Start the discussion.