From a44fed8e1953dbc24d43b9f3757f16a8b104f731 Mon Sep 17 00:00:00 2001 From: SandroMaglione Date: Sat, 23 Mar 2024 06:38:00 +0900 Subject: [PATCH] running `Effect` --- packages/fpdart/lib/src/effect.dart | 149 +++++++++++++++------------- 1 file changed, 81 insertions(+), 68 deletions(-) diff --git a/packages/fpdart/lib/src/effect.dart b/packages/fpdart/lib/src/effect.dart index 1b692bd..ee10bb2 100644 --- a/packages/fpdart/lib/src/effect.dart +++ b/packages/fpdart/lib/src/effect.dart @@ -37,7 +37,9 @@ EffectGen _effectGen(E? env) => ( final run = effect.asEffect._unsafeRun(env); if (run is Future) { throw _EffectThrow( - Die.current("Cannot execute a Future using sync"), + Die.current( + Exception("gen.sync cannot execute async Effect"), + ), ); } @@ -75,50 +77,77 @@ final class Effect extends IEffect { /// {@category execution} R runSync(E env) { - final result = _unsafeRun(env); - if (result is Future) { - throw Die.current(result); + try { + final result = _unsafeRun(env); + if (result is Future) { + throw Die.current( + Exception("runSync cannot execute async Effect"), + ); + } + + return switch (result) { + Left(value: final cause) => throw cause, + Right(value: final value) => value, + }; + } on Cause { + rethrow; + } catch (error, stackTrace) { + throw Die(error, stackTrace); } - - return switch (result) { - Left(value: final cause) => throw cause, - Right(value: final value) => value, - }; } /// {@category execution} Exit runSyncExit(E env) { - final result = _unsafeRun(env); - if (result is Future) { - return Left(Die.current("")); + try { + final result = _unsafeRun(env); + if (result is Future) { + return Left(Die.current( + Exception("runSyncExit cannot execute async Effect"), + )); + } + return result; + } on Cause catch (cause) { + return Left(cause); + } catch (error, stackTrace) { + return Left(Die(error, stackTrace)); } - return result; } /// {@category execution} Future runFuture(E env) async { - final result = _unsafeRun(env); - if (result is! Future) { - print( - "You can use runSync instead of runFuture since the Effect is synchronous", - ); + try { + final result = _unsafeRun(env); + if (result is! Future) { + return switch (result) { + Left(value: final cause) => throw cause, + Right(value: final value) => value, + }; + } + + return switch (await result) { + Left(value: final cause) => throw cause, + Right(value: final value) => value, + }; + } on Cause { + rethrow; + } catch (error, stackTrace) { + throw Die(error, stackTrace); } - - return switch (await result) { - Left(value: final cause) => throw cause, - Right(value: final value) => value, - }; } /// {@category execution} Future> runFutureExit(E env) async { - final result = _unsafeRun(env); - if (result is! Future) { - print( - "You can use runSyncExit instead of runFutureExit since the Effect is synchronous", - ); + try { + final result = _unsafeRun(env); + if (result is! Future) { + return result; + } + return result; + } on Cause catch (cause) { + return Left(cause); + } catch (error, stackTrace) { + return Left(Die(error, stackTrace)); } - return result; } /// {@category constructors} @@ -172,6 +201,17 @@ final class Effect extends IEffect { /// {@category constructors} factory Effect.succeed(R value) => Effect._((_) => Right(value)); + /// {@category constructors} + static Effect die(dynamic defect) => Effect._( + (_) => Left(Die.current(defect)), + ); + + /// {@category constructors} + static Effect functionDie(dynamic Function() run) => + Effect._( + (_) => Left(Die.current(run())), + ); + /// {@category constructors} static Effect unit = Effect._( (_) => const Right(fpdart_unit.unit), @@ -420,49 +460,22 @@ extension ProvideNever on Effect { ); /// {@category execution} - R runSyncNoEnv() { - final result = _unsafeRun(null); - if (result is Future) { - throw Die.current(result); - } - - return switch (result) { - Left(value: final cause) => throw cause, - Right(value: final value) => value, - }; - } + R runSyncNoEnv() => Effect._( + (_) => _unsafeRun(null), + ).runSync(null); /// {@category execution} - Exit runSyncExitNoEnv() { - final result = _unsafeRun(null); - if (result is Future) { - return Left(Die.current("")); - } - return result; - } + Exit runSyncExitNoEnv() => Effect._( + (_) => _unsafeRun(null), + ).runSyncExit(null); /// {@category execution} - Future runFutureNoEnv() async { - final result = await _unsafeRun(null); - if (result is! Future) { - print( - "You can use runSync instead of runFuture since the Effect is synchronous", - ); - } - return switch (result) { - Left(value: final cause) => throw cause, - Right(value: final value) => value, - }; - } + Future runFutureNoEnv() async => Effect._( + (_) => _unsafeRun(null), + ).runFuture(null); /// {@category execution} - Future> runFutureExitNoEnv() async { - final result = _unsafeRun(null); - if (result is! Future) { - print( - "You can use runSync instead of runFuture since the Effect is synchronous", - ); - } - return result; - } + Future> runFutureExitNoEnv() async => Effect._( + (_) => _unsafeRun(null), + ).runFutureExit(null); }