Skip to content

Commit

Permalink
Method: apply (#1)
Browse files Browse the repository at this point in the history
`apply` method that applies the content of Oks to a callable in a variadic fashion
  • Loading branch information
Carlsson87 authored and prewk committed Nov 23, 2017
1 parent 1c5c226 commit eb99451
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 1 deletion.
6 changes: 6 additions & 0 deletions spec/Result/ErrSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,10 @@ function it_converts_into_some_with_err()
$option->shouldHaveType(Some::class);
$option->unwrap()->shouldBe("error");
}

function it_does_not_apply_args_in_an_err()
{
$this->beConstructedWith("error");
$this->apply(new Ok(123))->isErr()->shouldBe(true);
}
}
33 changes: 32 additions & 1 deletion spec/Result/OkSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use Exception;
use Prewk\Option\{Some, None};
use Prewk\Result\Ok;
use Prewk\Result\{Ok, Err};
use PhpSpec\ObjectBehavior;
use Prewk\Result\ResultException;

Expand Down Expand Up @@ -137,4 +137,35 @@ function it_converts_into_none_with_err()

$option->shouldHaveType(None::class);
}

function it_can_apply_argument_to_function()
{
$this->beConstructedWith(function($one) {
return $one;
});
$arg = new Ok(13);
$this->apply($arg)->unwrap()->shouldBe(13);
}

function it_can_apply_multiple_arguments_to_function()
{
$this->beConstructedWith(function($x, $y, $z) {
return $x + $y + $z;
});
$this->apply(new Ok(1), new Ok(2), new Ok(3))->unwrap()->shouldBe(6);
}

function it_returns_err_when_one_of_args_is_err()
{
$this->beConstructedWith(function($x, $y, $z) {
return $x + $y + $z;
});
$this->apply(new Ok(1), new Ok(2), new Err(3))->isErr()->shouldBe(true);
}

function it_throws_if_non_callable_value_is_applied_to_arguments()
{
$this->beConstructedWith(1);
$this->shouldThrow(ResultException::class)->during("apply");
}
}
8 changes: 8 additions & 0 deletions src/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,12 @@ public function expect(Exception $msg);
* @return mixed
*/
public function unwrapErr();

/**
* Applies values inside the given Results to the function in this Result.
*
* @param Result[] ...$args Results to apply the function to.
* @return Result
*/
public function apply(Result ...$args): Result;
}
11 changes: 11 additions & 0 deletions src/Result/Err.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,17 @@ public function unwrapErr()
{
return $this->err;
}

/**
* Applies values inside the given Results to the function in this Result.
*
* @param Result[] ...$args Results to apply the function to.
* @return Result
*/
public function apply(Result ...$args): Result
{
return $this;
}

/**
* Converts from Result<T, E> to Option<T>, and discarding the error, if any
Expand Down
23 changes: 23 additions & 0 deletions src/Result/Ok.php
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,29 @@ public function unwrapErr()
throw new ResultException("Unwrapped with the expecation of Err, but found Ok");
}

/**
* Applies values inside the given Results to the function in this Result.
*
* @param Result[] ...$args Results to apply the function to.
* @return Result
*/
public function apply(Result ...$args): Result
{
if (!is_callable($this->value)) {
throw new ResultException("Tried to apply a non-callable to arguments");
}
return array_reduce($args, function(Result $final, Result $result) {
return $final->andThen(function(array $array) use ($result) {
return $result->map(function($x) use ($array) {
array_push($array, $x);
return $array;
});
});
}, new static([]))->map(function(array $argArray) {
return call_user_func_array($this->value, $argArray);
});
}

/**
* Converts from Result<T, E> to Option<T>, and discarding the error, if any
*
Expand Down

0 comments on commit eb99451

Please sign in to comment.