Skip to content

Commit

Permalink
Support variadic pass-through arguments (#3)
Browse files Browse the repository at this point in the history
Makes it easier to handle arguments acquired in consecutive steps that depend on earlier results
  • Loading branch information
prewk committed Feb 3, 2018
1 parent eb99451 commit 2f19406
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 13 deletions.
14 changes: 8 additions & 6 deletions helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
* @author Oskar Thornblad
*/

if (!function_exists("ok")) {
if (!function_exists("ok")) {
/**
* Represent a successful result
*
* @codeCoverageIgnore
* @param mixed $value
* @param array ...$pass
* @return Prewk\Result\Ok
*/
function ok($value = null): Prewk\Result\Ok {
return new Prewk\Result\Ok($value);
function ok($value = null, ...$pass): Prewk\Result\Ok {
return new Prewk\Result\Ok($value, ...$pass);
}
}

Expand All @@ -23,10 +24,11 @@ function ok($value = null): Prewk\Result\Ok {
* Represent a failed result
*
* @codeCoverageIgnore
* @param mixed $value
* @param $err
* @param array ...$pass
* @return Prewk\Result\Err
*/
function err($err): Prewk\Result\Err {
return new Prewk\Result\Err($err);
function err($err, ...$pass): Prewk\Result\Err {
return new Prewk\Result\Err($err, $pass);
}
}
33 changes: 33 additions & 0 deletions spec/Result/ErrSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -153,4 +153,37 @@ function it_does_not_apply_args_in_an_err()
$this->beConstructedWith("error");
$this->apply(new Ok(123))->isErr()->shouldBe(true);
}

function it_mapErrs_with_pass_args()
{
$this->beConstructedWith("foo", "bar", "baz");
$result = $this->mapErr(function($foo, $bar, $baz) {
return $foo . $bar . $baz;
});

$result->shouldHaveType(Err::class);
$result->unwrapErr()->shouldBe("foobarbaz");
}

function it_orElses_with_pass_args()
{
$this->beConstructedWith("foo", "bar", "baz");
$result = $this->orElse(function($foo, $bar, $baz) {
return new Err($foo . $bar . $baz);
});

$result->unwrapErr()->shouldBe("foobarbaz");
}

function its_with_method_adds_args()
{
$this->beConstructedWith("foo");
$this->with("bar", "baz");

$result = $this->orElse(function($foo, $bar, $baz) {
return new Err($foo . $bar . $baz);
});

$result->unwrapErr()->shouldBe("foobarbaz");
}
}
33 changes: 33 additions & 0 deletions spec/Result/OkSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,37 @@ function it_throws_if_non_callable_value_is_applied_to_arguments()
$this->beConstructedWith(1);
$this->shouldThrow(ResultException::class)->during("apply");
}

function it_maps_with_pass_args()
{
$this->beConstructedWith("foo", "bar", "baz");
$result = $this->map(function($foo, $bar, $baz) {
return $foo . $bar . $baz;
});

$result->shouldHaveType(Ok::class);
$result->unwrap()->shouldBe("foobarbaz");
}

function it_andThens_with_pass_args()
{
$this->beConstructedWith("foo", "bar", "baz");
$result = $this->andThen(function($foo, $bar, $baz) {
return new Ok($foo . $bar . $baz);
});

$result->unwrap()->shouldBe("foobarbaz");
}

function its_with_method_adds_args()
{
$this->beConstructedWith("foo");
$this->with("bar", "baz");

$result = $this->andThen(function($foo, $bar, $baz) {
return new Ok($foo . $bar . $baz);
});

$result->unwrap()->shouldBe("foobarbaz");
}
}
8 changes: 8 additions & 0 deletions src/Result.php
Original file line number Diff line number Diff line change
Expand Up @@ -150,4 +150,12 @@ public function unwrapErr();
* @return Result
*/
public function apply(Result ...$args): Result;

/**
* The attached pass-through args will be unpacked into extra args into chained closures
*
* @param array ...$args
* @return Result
*/
public function with(...$args): Result;
}
28 changes: 24 additions & 4 deletions src/Result/Err.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,21 @@ class Err implements Result
*/
private $err;

/**
* @var array
*/
private $pass;

/**
* Err constructor.
*
* @param mixed $err
* @param array ...$pass
*/
public function __construct($err)
public function __construct($err, ...$pass)
{
$this->err = $err;
$this->pass = $pass;
}

/**
Expand Down Expand Up @@ -75,7 +82,7 @@ public function map(Closure $mapper): Result
*/
public function mapErr(Closure $mapper): Result
{
return new self($mapper($this->err));
return new self($mapper($this->err, ...$this->pass));
}

/**
Expand Down Expand Up @@ -131,7 +138,7 @@ public function or(Result $res): Result
*/
public function orElse(Closure $op): Result
{
$result = $op($this->err);
$result = $op($this->err, ...$this->pass);

if (!($result instanceof Result)) {
throw new ResultException("Op must return a Result");
Expand Down Expand Up @@ -159,7 +166,7 @@ public function unwrapOr($optb)
*/
public function unwrapOrElse(Closure $op)
{
return $op($this->err);
return $op($this->err, ...$this->pass);
}

/**
Expand Down Expand Up @@ -231,4 +238,17 @@ public function err(): Option
{
return new Some($this->err);
}

/**
* The attached pass-through args will be unpacked into extra args into chained closures
*
* @param array ...$args
* @return Result
*/
public function with(...$args): Result
{
$this->pass = $args;

return $this;
}
}
26 changes: 23 additions & 3 deletions src/Result/Ok.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,21 @@ class Ok implements Result
*/
private $value;

/**
* @var array
*/
private $pass;

/**
* Ok constructor.
*
* @param mixed $value
* @param array ...$pass
*/
public function __construct($value)
public function __construct($value, ...$pass)
{
$this->value = $value;
$this->pass = $pass;
}

/**
Expand Down Expand Up @@ -64,7 +71,7 @@ public function isErr(): bool
*/
public function map(Closure $mapper): Result
{
return new self($mapper($this->value));
return new self($mapper($this->value, ...$this->pass));
}

/**
Expand Down Expand Up @@ -109,7 +116,7 @@ public function and(Result $res): Result
*/
public function andThen(Closure $op): Result
{
$result = $op($this->value);
$result = $op($this->value, ...$this->pass);

if (!($result instanceof Result)) {
throw new ResultException("Op must return a Result");
Expand Down Expand Up @@ -238,4 +245,17 @@ public function err(): Option
{
return new None;
}

/**
* The attached pass-through args will be unpacked into extra args into chained closures
*
* @param array ...$args
* @return Result
*/
public function with(...$args): Result
{
$this->pass = $args;

return $this;
}
}

0 comments on commit 2f19406

Please sign in to comment.