diff --git a/lib/option.dart b/lib/option.dart index 7cb4f83..dcec364 100644 --- a/lib/option.dart +++ b/lib/option.dart @@ -1,6 +1,5 @@ library option; -export 'src/option/future_option.dart'; export 'src/option/future_option_extensions.dart'; export 'src/option/future_result_and_option_extensions.dart'; export 'src/option/option.dart'; diff --git a/lib/result.dart b/lib/result.dart index eda8725..c053e8b 100644 --- a/lib/result.dart +++ b/lib/result.dart @@ -1,7 +1,6 @@ library result; export 'src/result/execute_protected.dart'; -export 'src/result/future_result.dart'; export 'src/result/record_to_result_extensions.dart'; export 'src/result/result.dart'; export 'src/result/result_extensions.dart'; diff --git a/lib/src/option/README.md b/lib/src/option/README.md index 1cecb54..02c9b8c 100644 --- a/lib/src/option/README.md +++ b/lib/src/option/README.md @@ -43,6 +43,12 @@ expect(earlyReturn(2), const None()); ``` This is a powerful concept and make you code much more concise without losing any safety. +For async, use `Option.async` e.g. +```dart +FutureOption earlyReturn() => Option.async(($) async { + ... +}); +``` ### To Option or Not To Option If Dart already supports nullable types, why use an diff --git a/lib/src/option/future_option.dart b/lib/src/option/future_option.dart index 50f4940..42ae10f 100644 --- a/lib/src/option/future_option.dart +++ b/lib/src/option/future_option.dart @@ -1,7 +1,4 @@ -import 'dart:async'; - -import 'package:rust_core/option.dart'; -import 'package:rust_core/result.dart'; +part of 'option.dart'; /// {@macro futureOption} typedef FutureOption = Future>; @@ -110,7 +107,16 @@ extension FutureOptionExtension on FutureOption { return then((option) => option.zipWith(other, f)); } + //************************************************************************// + Future toNullable() { return then((option) => option.toNullable()); } + + //************************************************************************// + + // ignore: library_private_types_in_public_api + Future operator [](_OptionEarlyReturnKey op) { + return then((value) => value[op]); + } } diff --git a/lib/src/option/option.dart b/lib/src/option/option.dart index 32da082..bb18aa7 100644 --- a/lib/src/option/option.dart +++ b/lib/src/option/option.dart @@ -1,6 +1,10 @@ +import 'dart:async'; + import 'package:rust_core/result.dart'; import 'package:rust_core/panic.dart'; +part 'future_option.dart'; + sealed class Option { /// Creates a context for early return, similar to "Do notation". Works like the Rust "?" operator, which is a /// "Early Return Operator". Here "$" is used as the "Early Return Key". when "$" is used on a type [None], @@ -28,13 +32,13 @@ sealed class Option { /// "Early Return Operator". Here "$" is used as the "Early Return Key". when "$" is used on a type [None], /// immediately the context that "$" belongs to is returned with None(). e.g. /// ``` - /// Option intNone() => const None(); - /// - /// Option earlyReturn(int val) => Option(($){ - /// int x = intNone()[$]; // returns [None] immediately - /// return Some(val + 3); - /// }); - /// expect(earlyReturn(2), const None()); + /// FutureOption intNone() async => const None(); + /// + /// FutureOption earlyReturn(int val) => Option.async(($) async { + /// int x = await intNone()[$]; // returns [None] immediately + /// return Some(x + 3); + /// }); + /// expect(await earlyReturn(2), const None()); ///``` /// This should be used at the top level of a function as above. Passing "$" to any other functions, nesting, or /// attempting to bring "$" out of the original scope should be avoided. @@ -478,14 +482,6 @@ typedef _OptionEarlyReturnFunction = Option Function( typedef _OptionAsyncEarlyReturnFunction = Future> Function( _OptionEarlyReturnKey); -extension AsyncOptionEarlyReturnExtension - on Future> { - // ignore: library_private_types_in_public_api - Future operator [](_OptionEarlyReturnKey op) { - return then((value) => value[op]); - } -} - //************************************************************************// const none = None(); diff --git a/lib/src/result/README.md b/lib/src/result/README.md index b9cf697..74575d7 100644 --- a/lib/src/result/README.md +++ b/lib/src/result/README.md @@ -152,7 +152,7 @@ Result earlyReturn() => Result(($) { // Early Return Key int y = 2; // The function will return here will the Err value; int x = innerErrFn()[$]; - return Ok(x.unwrap() + y); + return Ok(x + y); }); expect(earlyReturn().unwrapErr(), "message"); @@ -160,6 +160,13 @@ expect(earlyReturn().unwrapErr(), "message"); Using the Early Return Key Notation reduces the need for pattern matching or checking, in a safe way. This is quite a powerful tool. See [here](#pattern-matching-vs-early-return-key) for another example. +For async, use the `Result.async` e.g. +```dart +FutureResult earlyReturn() => Result.async(($) async { + ... +}); +``` + ## How to Never Unwrap Incorrectly In Rust, as here, it is possible to unwrap values that should not be unwrapped: ```dart diff --git a/lib/src/result/future_result.dart b/lib/src/result/future_result.dart index e09210c..6f11e27 100644 --- a/lib/src/result/future_result.dart +++ b/lib/src/result/future_result.dart @@ -1,6 +1,4 @@ -import 'dart:async'; - -import 'package:rust_core/result.dart'; +part of 'result.dart'; /// {@macro futureResult} typedef FutureResult = Future>; @@ -167,4 +165,11 @@ extension FutureResultExtension on FutureResult { FutureResult copy() { return then((result) => result.copy()); } + + //************************************************************************// + + // ignore: library_private_types_in_public_api + Future operator [](_ResultEarlyReturnKey op) { + return then((value) => value[op]); + } } diff --git a/lib/src/result/result.dart b/lib/src/result/result.dart index ec27d0c..8d71b42 100644 --- a/lib/src/result/result.dart +++ b/lib/src/result/result.dart @@ -1,6 +1,10 @@ +import 'dart:async'; + import 'package:rust_core/typedefs.dart'; import 'package:rust_core/panic.dart'; +part 'future_result.dart'; + /// {@template result} /// [Result] class representing the type union between [Ok] and [Err]. /// @@ -10,18 +14,22 @@ import 'package:rust_core/panic.dart'; /// .org/std/result/enum.Result.html /// {@endtemplate} sealed class Result { - /// Creates a context for early return, similar to "Do notation". Works like the Rust "?" operator, which is a - /// "Early Return Operator". Here "$" is used as the "Early Return Key". when "$" is used on a type [Err], - /// immediately the context that "$" belongs to is returned with that [Err]. e.g. - /// ``` - /// Result innerFn(){ - /// return Err("message"); - /// } + + /// Creates a context for early return, similar to "Do notation". + /// Here "$" is used as the "Early Return Key". when "$" is used on a type [Err], + /// immediately the context that "$" belongs to is returned with that [Err]. + /// Works like the Rust "?" operator, which is a "Early Return Operator". + /// e.g. + /// ```dart + /// Result innerFn() => Err("message"); + /// + /// Result innerFn2() => Ok(1); + /// /// Result earlyReturn() => Result(($) { /// int y = 2; - /// // the function will stop here since an Err was returned - /// int x = innerFn()[$]; - /// return Ok(x + y); + /// int x = innerFn()[$]; // returns [Err] here immediately + /// int z = innerFn2()[$]; // innerFn2 will not be executed + /// return Ok(x + y + z); /// }); /// } /// expect(earlyReturn().unwrapErr(), "message"); @@ -36,27 +44,21 @@ sealed class Result { } } - /// Similar to [Result()], but works in an asynchronous context. - /// - /// Creates a context for early return, similar to "Do notation". Works like the Rust "?" operator, which is a - /// "Early Return Operator". Here "$" is used as the "Early Return Key". when "$" is used on a type [Err], - /// immediately the context that "$" belongs to is returned with that [Err]. e.g. + /// Creates a async context for early return, similar to "Do notation". + /// Here "$" is used as the "Early Return Key". when "$" is used on a type [Err], + /// immediately the context that "$" belongs to is returned with that [Err]. + /// Works like the Rust "?" operator, which is a "Early Return Operator". + /// e.g. /// /// ```dart - /// FutureResult innerFn() async { - /// return Err("message"); - /// } + /// FutureResult innerFn() async => Err("message"); /// - /// FutureResult innerFn2() async { - /// return Ok(1); - /// } + /// FutureResult innerFn2() async => Ok(1); /// - /// FutureResult earlyReturn() => Result.earlyAsync(($) async { + /// FutureResult earlyReturn() => Result.early(($) async { /// int y = 2; - /// // the function will stop here since an Err was returned - /// int x = await innerFn()[$]; - /// // innerFn2 will not be executed - /// int z = await innerFn2()[$]; + /// int x = await innerFn()[$]; // returns [Err] here immediately + /// int z = await innerFn2()[$]; // innerFn2 will not be executed /// return Ok(x + y + z); /// }); /// } @@ -64,8 +66,7 @@ sealed class Result { ///``` /// /// This should be used at the top level of a function as above. Passing "$" to any other functions, nesting, or - /// attempting to bring "$" out of the original scope should be avoided. Also, using the method [catchError] on the futures after - /// the `[$]` operator might lead to unexpected behaviour. + /// attempting to bring "$" out of the original scope should be avoided. static Future> async( // ignore: library_private_types_in_public_api _AsyncResultEarlyReturnFunction fn, @@ -643,13 +644,6 @@ typedef _ResultEarlyReturnFunction = Result Function( typedef _AsyncResultEarlyReturnFunction = Future> Function(_ResultEarlyReturnKey); -extension AsyncResultEarlyReturnExtension - on Future> { - Future operator [](_ResultEarlyReturnKey op) { - return then((value) => value[op]); - } -} - //************************************************************************// const okay = Ok(unit);