Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(option): add Option::proceed() method #433

Merged
merged 3 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions src/Psl/Option/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,29 @@ public function contains(mixed $value): bool
return false;
}

/**
* Matches the contained option value with the provided closures and returns the result.
*
* @template Ts
*
* @param (Closure(T): Ts) $some A closure to be called when the option is some.
* The closure must accept the option value as its only argument and can return a value.
* Example: `fn($value) => $value + 10`
* @param (Closure(): Ts) $none A closure to be called when the option is none.
* The closure must not accept any arguments and can return a value.
* Example: `fn() => 'Default value'`
*
* @return Ts The result of calling the appropriate closure.
*/
public function proceed(Closure $some, Closure $none): mixed
{
if ($this->option !== null) {
return $some($this->option[0]);
}

return $none();
}

/**
* Maps an `Option<T>` to `Option<Tu>` by applying a function to a contained value.
*
Expand Down
21 changes: 21 additions & 0 deletions tests/static-analysis/Option/proceed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

use Psl\Option;

function proceed(): void
{
/**
* @param Option\Option<int> $option
*
* @return non-empty-string
*/
function test_proceed(Option\Option $option): string
{
return $option->proceed(
static fn (int $value) => "There is $value of them.",
static fn () => 'There are none.',
);
}
}
11 changes: 11 additions & 0 deletions tests/unit/Option/NoneTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Psl\Comparison\Order;
use Psl\Option;
use Psl\Option\Exception\NoneException;
use Psl\Str;

final class NoneTest extends TestCase
{
Expand Down Expand Up @@ -84,6 +85,16 @@ public function testContains(): void
static::assertFalse($option->contains(4));
}

public function testProceed(): void
{
$result = Option\none()->proceed(
static fn ($i) => Str\format('Value is %d', $i),
static fn () => 'There is no value',
);

static::assertSame('There is no value', $result);
}

public function testMap(): void
{
$option = Option\none();
Expand Down
11 changes: 11 additions & 0 deletions tests/unit/Option/SomeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Psl\Comparison\Equable;
use Psl\Comparison\Order;
use Psl\Option;
use Psl\Str;
use Psl\Tests\Fixture;
use Psl\Type;

Expand Down Expand Up @@ -83,6 +84,16 @@ public function testContains(): void
static::assertTrue($option->contains(2));
}

public function testProceed(): void
{
$result = Option\some(1)->proceed(
static fn ($i) => Str\format('Value is %d', $i),
static fn () => 'There is no value',
);

static::assertSame('Value is 1', $result);
}

public function testMap(): void
{
$option = Option\some(2);
Expand Down