From 03613bd00fbd497a630f5bb67b73b737185789e3 Mon Sep 17 00:00:00 2001 From: kakiuchi-shigenao Date: Thu, 8 May 2025 15:43:03 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20Result=E3=83=A2=E3=83=8A=E3=83=89?= =?UTF-8?q?=E3=81=ABmatch=E3=83=A1=E3=82=BD=E3=83=83=E3=83=89=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=E3=81=97=E3=80=81Ok=E3=81=A8Err=E3=81=AE?= =?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E7=B5=B1=E4=B8=80=20Fixes=20#38?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Result.php | 12 +++++ src/Result/Err.php | 6 +++ src/Result/Ok.php | 6 +++ tests/Unit/Result/MatchTest.php | 93 +++++++++++++++++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 tests/Unit/Result/MatchTest.php diff --git a/src/Result.php b/src/Result.php index 0cf5999..c4cce19 100644 --- a/src/Result.php +++ b/src/Result.php @@ -190,4 +190,16 @@ public function ok(): Option; * @return Option */ public function err(): Option; + + /** + * Applies one of two functions depending on whether the result is Ok or Err. + * Comparable to neverthrow's `match` method. + * + * @template U + * @template V + * @param Closure(T): U $okFn Function to apply if the Result is Ok + * @param Closure(E): V $errFn Function to apply if the Result is Err + * @return U|V The result of applying the appropriate function + */ + public function match(Closure $okFn, Closure $errFn): mixed; } diff --git a/src/Result/Err.php b/src/Result/Err.php index 35bed4a..02fff8a 100644 --- a/src/Result/Err.php +++ b/src/Result/Err.php @@ -245,4 +245,10 @@ public function getIterator(): Traversable { return new EmptyIterator(); } + + #[Override] + public function match(Closure $okFn, Closure $errFn): mixed + { + return $errFn($this->value); + } } diff --git a/src/Result/Ok.php b/src/Result/Ok.php index fd3ff57..77aeb9d 100644 --- a/src/Result/Ok.php +++ b/src/Result/Ok.php @@ -238,4 +238,10 @@ public function getIterator(): Traversable { yield $this->value; } + + #[Override] + public function match(Closure $okFn, Closure $errFn): mixed + { + return $okFn($this->value); + } } diff --git a/tests/Unit/Result/MatchTest.php b/tests/Unit/Result/MatchTest.php new file mode 100644 index 0000000..4c618a1 --- /dev/null +++ b/tests/Unit/Result/MatchTest.php @@ -0,0 +1,93 @@ + + */ + public function createResult(): Result + { + return Result\ok(42); + } + + /** + * @template T + * @template E + * @template U + * @param Result $result + * @param U $okValue Value to return when Result is Ok + * @param U $errValue Value to return when Result is Err + * @param U $expected Expected outcome + * @param array $expectedCalls Values that should be passed to the callbacks + */ + #[Test] + #[TestDox('match test')] + #[DataProvider('matchMatrix')] + public function match( + Result $result, + mixed $okValue, + mixed $errValue, + mixed $expected, + array $expectedCalls + ): void { + $calls = []; + + $actual = $result->match( + static function (mixed $value) use ($okValue, &$calls): mixed { + $calls[] = $value; + + return $okValue; + }, + static function (mixed $value) use ($errValue, &$calls): mixed { + $calls[] = $value; + + return $errValue; + } + ); + + Assert::assertSame($expected, $actual); + Assert::assertSame($expectedCalls, $calls); + } + + /** + * @return iterable|Result\Err, + * string, + * string, + * string, + * array + * }> + */ + public static function matchMatrix(): iterable + { + yield 'ok' => [ + Result\ok(42), + 'success', + 'failure', + 'success', + [42], + ]; + + yield 'err' => [ + Result\err('error'), + 'success', + 'failure', + 'failure', + ['error'], + ]; + } +}