From d23d4fa6a66659e10cb68bce281e54d449b3cdac Mon Sep 17 00:00:00 2001 From: mcmah309 Date: Sat, 2 Mar 2024 01:24:03 +0000 Subject: [PATCH] feat: Remove the need for option method delegation --- lib/src/option/future_option.dart | 4 - lib/src/option/option.dart | 193 ++++++++++++++++++------------ 2 files changed, 114 insertions(+), 83 deletions(-) diff --git a/lib/src/option/future_option.dart b/lib/src/option/future_option.dart index ceb4a78..ed27d5c 100644 --- a/lib/src/option/future_option.dart +++ b/lib/src/option/future_option.dart @@ -17,10 +17,6 @@ extension FutureOptionExtension on FutureOption { option.isSome() ? f(option.unwrap()) : Future.value(const None())); } - Future> copy() { - return then((option) => option.copy()); - } - Future expect(String msg) { return then((option) => option.expect(msg)); } diff --git a/lib/src/option/option.dart b/lib/src/option/option.dart index 02c5e1a..5ff0f16 100644 --- a/lib/src/option/option.dart +++ b/lib/src/option/option.dart @@ -21,6 +21,7 @@ extension type const Option._(T? v) { ///``` /// 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. + // ignore: library_private_types_in_public_api factory Option(_OptionEarlyReturnFunction fn) { try { return fn(const _OptionEarlyReturnKey._()); @@ -55,30 +56,34 @@ extension type const Option._(T? v) { /// Returns None if the option is None, otherwise returns [other]. Option and(Option other) { - return this != null ? (this as Some).and(other) : (this as None).and(other); + return v == null ? const None() : other; } ///Returns None if the option is None, otherwise calls f with the wrapped value and returns the result. Some ///languages call this operation flatmap. Option andThen(Option Function(T) f) { - return this != null ? (this as Some).andThen(f) : (this as None).andThen(f); + return v == null ? const None() : f(v!); } - /// Shallow copies this Option - Option copy() { - return this != null ? (this as Some).copy() : (this as None).copy(); - } + // copy: Does not make sense to add here since this is an extension type /// Returns the contained Some value if [Some], otherwise throws a [Panic]. T expect(String msg) { - return this != null ? (this as Some).expect(msg) : (this as None).expect(msg); + return v == null ? throw Panic(onValue: this, reason: msg) : v!; } /// Returns None if the option is None, otherwise calls predicate with the wrapped value and returns /// Some(t) if predicate returns true (where t is the wrapped value), and // None if predicate returns false Option filter(bool Function(T) predicate) { - return this is Some ? (this as Some).filter(predicate) : (this as None).filter(predicate); + if (v == null) { + return const None(); + } else { + if (predicate(v!)) { + return Some(v!); + } + return const None(); + } } // flatten: Added as extension @@ -91,63 +96,104 @@ extension type const Option._(T? v) { /// Calls the provided closure with a reference to the contained value Option inspect(Function(T) f) { - return this is Some ? (this as Some).inspect(f) : (this as None).inspect(f); + if (v == null) { + return this; + } else { + f(v!); + return this; + } } /// Returns true if the option is a None value. bool isNone() { - return this is Some ? (this as Some).isNone() : (this as None).isNone(); + return this == null; } /// Returns true if the option is a Some value. bool isSome() { - return this is Some ? (this as Some).isSome() : (this as None).isSome(); + return this != null; } /// Returns true if the option is a Some and the value inside of it matches a predicate. bool isSomeAnd(bool Function(T) f) { - return this is Some ? (this as Some).isSomeAnd(f) : (this as None).isSomeAnd(f); + if (v == null) { + return false; + } else { + return f(v!); + } } /// Returns an iterable over the possibly contained value. Iterable iter() { - return this is Some ? (this as Some).iter() : (this as None).iter(); + if (v == null) { + return const []; + } else { + return [v!]; + } } /// Maps an this Option to Option by applying a function to a contained value (if Some) or returns None (if /// None). - Option map(U Function(T) f){ - return this is Some ? (this as Some).map(f) : (this as None).map(f); + Option map(U Function(T) f) { + if (v == null) { + return const None(); + } else { + return Some(f(v!)); + } } /// Returns the provided default result (if none), or applies a function to the contained value (if any). U mapOr(U defaultValue, U Function(T) f) { - return this is Some ? (this as Some).mapOr(defaultValue, f) : (this as None).mapOr(defaultValue, f); + if (v == null) { + return defaultValue; + } else { + return f(v!); + } } /// Computes a default function result (if none), or applies a different function to the contained value (if any). U mapOrElse(U Function() defaultFn, U Function(T) f) { - return this is Some ? (this as Some).mapOrElse(defaultFn, f) : (this as None).mapOrElse(defaultFn, f); + if (v == null) { + return defaultFn(); + } else { + return f(v!); + } } /// Transforms the Option into a Result, mapping Some(v) to Ok(v) and None to Err(err). Result okOr(E err) { - return this is Some ? (this as Some).okOr(err) : (this as None).okOr(err); + if (v == null) { + return Err(err); + } else { + return Ok(v!); + } } /// Transforms the Option into a Result, mapping Some(v) to Ok(v) and None to Err(err()). Result okOrElse(E Function() errFn) { - return this is Some ? (this as Some).okOrElse(errFn) : (this as None).okOrElse(errFn); + if (v == null) { + return Err(errFn()); + } else { + return Ok(v!); + } } /// Returns the option if it contains a value, otherwise returns other. Option or(Option other) { - return this is Some ? (this as Some).or(other) : (this as None).or(other); + if (v == null) { + return other; + } else { + return Some(v!); + } } /// Returns the option if it contains a value, otherwise calls f and returns the result. Option orElse(Option Function() f) { - return this is Some ? (this as Some).orElse(f) : (this as None).orElse(f); + if (v == null) { + return f(); + } else { + return Some(v!); + } } // Option replace(value); // not possible, otherwise not const @@ -160,34 +206,70 @@ extension type const Option._(T? v) { /// Returns the contained Some value, consuming the self value. T unwrap() { - return this is Some ? (this as Some).unwrap() : (this as None).unwrap(); + if (v == null) { + throw Panic(reason: "called `unwrap` a None type"); + } else { + return v!; + } } /// Returns the contained Some value or a provided default. T unwrapOr(T defaultValue) { - return this is Some ? (this as Some).unwrapOr(defaultValue) : (this as None).unwrapOr(defaultValue); + if (v == null) { + return defaultValue; + } else { + return v!; + } } /// Returns the contained Some value or computes it from a closure. T unwrapOrElse(T Function() f) { - return this is Some ? (this as Some).unwrapOrElse(f) : (this as None).unwrapOrElse(f); + if (v == null) { + return f(); + } else { + return v!; + } } // unzip: Added as extension /// Returns Some if exactly one of self, [other] is Some, otherwise returns None. Option xor(Option other) { - return this is Some ? (this as Some).xor(other) : (this as None).xor(other); + if (v == null) { + if (other.isSome()) { + return other; + } + return const None(); + } else { + if (other.isSome()) { + return const None(); + } + return Some(v!); + } } /// Zips self with another Option. Option<(T, U)> zip(Option other) { - return this is Some ? (this as Some).zip(other) : (this as None).zip(other); + if (v == null) { + return const None(); + } else { + if (other.isSome()) { + return Some((v!, other.unwrap())); + } + return const None(); + } } /// Zips self and another Option with function f Option zipWith(Option other, R Function(T, U) f) { - return this is Some ? (this as Some).zipWith(other, f) : (this as None).zipWith(other, f); + if (v == null) { + return const None(); + } else { + if (other.isSome()) { + return Some(f(v!, other.unwrap())); + } + return const None(); + } } //************************************************************************// @@ -202,34 +284,33 @@ extension type const Option._(T? v) { /// Functions an "Early Return Operator" when given an "Early Return key" "$". See [Option.$] for more information. T operator [](_OptionEarlyReturnKey op) // ignore: library_private_types_in_public_api { - return this is Some ? (this as Some)[op] : (this as None)[op]; + if (v == null) { + throw const _OptionEarlyReturnNotification(); + } else { + return v!; + } } } extension type const Some._(T v) implements Option, Object { const Some(T v) : this._(v); - Option and(Option other) { return other; } - Option andThen(Option Function(T self) f) { return f(v); } - Option copy() { return Some(v); } - T expect(String msg) { return v; } - Option filter(bool Function(T self) predicate) { if (predicate(v)) { return Some(v); @@ -237,88 +318,71 @@ extension type const Some._(T v) implements Option, Object return const None(); } - Option inspect(Function(T self) f) { f(v); return this; } - bool isNone() { return false; } - bool isSome() { return true; } - bool isSomeAnd(bool Function(T self) f) { return f(v); } - Iterable iter() sync* { yield v; } - Option map(U Function(T self) f) { return Some(f(v)); } - U mapOr(U defaultValue, U Function(T) f) { return f(v); } - U mapOrElse(U Function() defaultFn, U Function(T) f) { return f(v); } - Result okOr(E err) { return Ok(v); } - Result okOrElse(E Function() errFn) { return Ok(v); } - Option or(Option other) { return Some(v); } - Option orElse(Option Function() f) { return Some(v); } - T? toNullable() { return v; } - T unwrap() { return v; } - T unwrapOr(T defaultValue) { return v; } - T unwrapOrElse(T Function() f) { return v; } - Option xor(Option other) { if (other.isSome()) { return const None(); @@ -326,7 +390,6 @@ extension type const Some._(T v) implements Option, Object return Some(v); } - Option<(T, U)> zip(Option other) { if (other.isSome()) { return Some((v, other.unwrap())); @@ -334,7 +397,6 @@ extension type const Some._(T v) implements Option, Object return const None(); } - Option zipWith(Option other, R Function(T p1, U p2) f) { if (other.isSome()) { return Some(f(v, other.unwrap())); @@ -344,7 +406,6 @@ extension type const Some._(T v) implements Option, Object //************************************************************************// - // ignore: library_private_types_in_public_api T operator [](_OptionEarlyReturnKey op) { return v; @@ -352,108 +413,86 @@ extension type const Some._(T v) implements Option, Object } extension type const None._(Null _) implements Option { - const None() : this._(null); - Option and(Option other) { return const None(); } - Option andThen(Option Function(T self) f) { return const None(); } - Option copy() { return const None(); } - T expect(String msg) { throw Panic(onValue: this, reason: msg); } - Option filter(bool Function(T self) predicate) { return const None(); } - Option inspect(Function(T self) f) { return this; } - bool isNone() { return true; } - bool isSome() { return false; } - bool isSomeAnd(bool Function(T self) f) { return false; } - Iterable iter() sync* {} - Option map(U Function(T self) f) { return const None(); } - U mapOr(U defaultValue, U Function(T) f) { return defaultValue; } - U mapOrElse(U Function() defaultFn, U Function(T) f) { return defaultFn(); } - Result okOr(E err) { return Err(err); } - Result okOrElse(E Function() errFn) { return Err(errFn()); } - Option or(Option other) { return other; } - Option orElse(Option Function() f) { return f(); } - T unwrap() { throw Panic(reason: "called `unwrap` a None type"); } - T unwrapOr(T defaultValue) { return defaultValue; } - T unwrapOrElse(T Function() f) { return f(); } - Option xor(Option other) { if (other.isSome()) { return other; @@ -461,26 +500,22 @@ extension type const None._(Null _) implements Option { return const None(); } - Option<(T, U)> zip(Option other) { return const None(); } - Option zipWith(Option other, R Function(T p1, U p2) f) { return const None(); } //************************************************************************// - T? toNullable() { return null; } //************************************************************************// - // ignore: library_private_types_in_public_api T operator [](_OptionEarlyReturnKey op) { throw const _OptionEarlyReturnNotification();