Change functions to properties
- Force PHP 8.4
This commit is contained in:
parent
6779b2c554
commit
483d7875d5
|
@ -17,7 +17,7 @@
|
||||||
"rss": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp.rss"
|
"rss": "https://git.bitbadger.solutions/bit-badger/inspired-by-fsharp.rss"
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": "8.2 - 8.3"
|
"php": ">=8.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"phpunit/phpunit": "^11",
|
"phpunit/phpunit": "^11",
|
||||||
|
|
4
composer.lock
generated
4
composer.lock
generated
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e08185f1629cdda5af3af5405a707797",
|
"content-hash": "0cd12c9ee6159a96158d62691add3401",
|
||||||
"packages": [],
|
"packages": [],
|
||||||
"packages-dev": [
|
"packages-dev": [
|
||||||
{
|
{
|
||||||
|
@ -1721,7 +1721,7 @@
|
||||||
"prefer-stable": false,
|
"prefer-stable": false,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "8.2 - 8.3"
|
"php": ">=8.4"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": [],
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.6.0"
|
||||||
|
|
|
@ -25,50 +25,38 @@ use InvalidArgumentException;
|
||||||
*
|
*
|
||||||
* @template T The type of value represented by this option
|
* @template T The type of value represented by this option
|
||||||
*/
|
*/
|
||||||
readonly class Option
|
class Option
|
||||||
{
|
{
|
||||||
/** @var T|null $value The value for this option */
|
/** @var T|null $value The value for this option */
|
||||||
private mixed $value;
|
private mixed $val;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param T|null $value The possibly null value for this option
|
* @param T|null $value The possibly null value for this option
|
||||||
*/
|
*/
|
||||||
private function __construct(mixed $value = null)
|
private function __construct(mixed $value = null)
|
||||||
{
|
{
|
||||||
$this->value = $value;
|
$this->val = $value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value of this option
|
* @var T The value of this option (read-only)
|
||||||
*
|
* @throws InvalidArgumentException If called on a `None` option
|
||||||
* @return T The value of the option
|
|
||||||
*/
|
*/
|
||||||
public function get(): mixed
|
public mixed $value {
|
||||||
{
|
get => match ($this->val) {
|
||||||
return match (true) {
|
null => throw new InvalidArgumentException('Cannot get the value of a None option'),
|
||||||
$this->isSome() => $this->value,
|
default => $this->val,
|
||||||
default => throw new InvalidArgumentException('Cannot get the value of a None option'),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var bool True if the option is `None`, false if it is `Some` */
|
||||||
* Does this option have a `None` value?
|
public bool $isNone {
|
||||||
*
|
get => is_null($this->val);
|
||||||
* @return bool True if the option is `None`, false if it is `Some`
|
|
||||||
*/
|
|
||||||
public function isNone(): bool
|
|
||||||
{
|
|
||||||
return is_null($this->value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var bool True if the option is `Some`, false if it is `None` */
|
||||||
* Does this option have a `Some` value?
|
public bool $isSome{
|
||||||
*
|
get => !$this->isNone;
|
||||||
* @return bool True if the option is `Some`, false if it is `None`
|
|
||||||
*/
|
|
||||||
public function isSome(): bool
|
|
||||||
{
|
|
||||||
return !$this->isNone();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +67,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function getOrDefault(mixed $default): mixed
|
public function getOrDefault(mixed $default): mixed
|
||||||
{
|
{
|
||||||
return $this->value ?? $default;
|
return $this->val ?? $default;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -91,18 +79,19 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function getOrCall(callable $f): mixed
|
public function getOrCall(callable $f): mixed
|
||||||
{
|
{
|
||||||
return $this->value ?? $f();
|
return $this->val ?? $f();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value, or throw the
|
* Get the value, or throw the exception using the given function
|
||||||
|
*
|
||||||
* @param callable(): Exception $exFunc A function to construct the exception to throw
|
* @param callable(): Exception $exFunc A function to construct the exception to throw
|
||||||
* @return T The value of the option if `Some`
|
* @return T The value of the option if `Some`
|
||||||
* @throws Exception If the option is `None`
|
* @throws Exception If the option is `None`
|
||||||
*/
|
*/
|
||||||
public function getOrThrow(callable $exFunc): mixed
|
public function getOrThrow(callable $exFunc): mixed
|
||||||
{
|
{
|
||||||
return $this->value ?? throw $exFunc();
|
return $this->val ?? throw $exFunc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,7 +106,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function bind(callable $f): Option
|
public function bind(callable $f): Option
|
||||||
{
|
{
|
||||||
return $this->isNone() ? $this : $f($this->get());
|
return $this->isNone ? $this : $f($this->val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,8 +119,8 @@ readonly class Option
|
||||||
public function contains(mixed $value, bool $strict = true): bool
|
public function contains(mixed $value, bool $strict = true): bool
|
||||||
{
|
{
|
||||||
return match (true) {
|
return match (true) {
|
||||||
$this->isNone() => false,
|
$this->isNone => false,
|
||||||
default => $strict ? $this->value === $value : $this->value == $value,
|
default => $strict ? $this->val === $value : $this->val == $value,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +132,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function exists(callable $f): bool
|
public function exists(callable $f): bool
|
||||||
{
|
{
|
||||||
return $this->isSome() ? $f($this->value) : false;
|
return $this->isSome ? $f($this->val) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,7 +144,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function map(callable $f): self
|
public function map(callable $f): self
|
||||||
{
|
{
|
||||||
return $this->isSome() ? self::Some($f($this->get())) : $this;
|
return $this->isSome ? self::Some($f($this->val)) : $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,8 +154,8 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function iter(callable $f): void
|
public function iter(callable $f): void
|
||||||
{
|
{
|
||||||
if ($this->isSome()) {
|
if ($this->isSome) {
|
||||||
$f($this->value);
|
$f($this->val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +167,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function filter(callable $f): self
|
public function filter(callable $f): self
|
||||||
{
|
{
|
||||||
return $this->isNone() || $this->exists($f) ? $this : self::None();
|
return $this->isNone || $this->exists($f) ? $this : self::None();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -188,7 +177,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function unwrap(): mixed
|
public function unwrap(): mixed
|
||||||
{
|
{
|
||||||
return $this->value;
|
return $this->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -210,7 +199,7 @@ readonly class Option
|
||||||
*/
|
*/
|
||||||
public function toArray(): array
|
public function toArray(): array
|
||||||
{
|
{
|
||||||
return $this->isSome() ? [$this->value] : [];
|
return $this->isSome ? [$this->val] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -221,8 +210,8 @@ readonly class Option
|
||||||
public function toPhpOption(): mixed
|
public function toPhpOption(): mixed
|
||||||
{
|
{
|
||||||
return match (true) {
|
return match (true) {
|
||||||
$this->isNone() && class_exists('PhpOption\None') => call_user_func('PhpOption\None::create'),
|
$this->isNone && class_exists('PhpOption\None') => call_user_func('PhpOption\None::create'),
|
||||||
class_exists('PhpOption\Some') => call_user_func('PhpOption\Some::create', $this->value),
|
class_exists('PhpOption\Some') => call_user_func('PhpOption\Some::create', $this->val),
|
||||||
default => throw new Error('PhpOption types could not be found'),
|
default => throw new Error('PhpOption types could not be found'),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ use InvalidArgumentException;
|
||||||
* @template TOK The type of the OK result
|
* @template TOK The type of the OK result
|
||||||
* @template TError The type of the error result
|
* @template TError The type of the error result
|
||||||
*/
|
*/
|
||||||
readonly class Result
|
class Result
|
||||||
{
|
{
|
||||||
/** @var Option<TOK> The OK value for this result */
|
/** @var Option<TOK> The OK value for this result */
|
||||||
private Option $okValue;
|
private Option $okValue;
|
||||||
|
@ -45,46 +45,24 @@ readonly class Result
|
||||||
$this->errorValue = Option::of($errorValue);
|
$this->errorValue = Option::of($errorValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var TOK The OK value (will throw if result is not OK) */
|
||||||
* Get the value for an `OK` result
|
public mixed $ok {
|
||||||
*
|
get => $this->okValue->value;
|
||||||
* @return TOK The OK value for this result
|
|
||||||
* @throws InvalidArgumentException If the result is an `Error` result
|
|
||||||
*/
|
|
||||||
public function getOK(): mixed
|
|
||||||
{
|
|
||||||
return $this->okValue->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var TError The error value (will throw if result is not Error) */
|
||||||
* Get the value for an `Error` result
|
public mixed $error {
|
||||||
*
|
get => $this->errorValue->value;
|
||||||
* @return TError The error value for this result
|
|
||||||
* @throws InvalidArgumentException If the result is an `OK` result
|
|
||||||
*/
|
|
||||||
public function getError(): mixed
|
|
||||||
{
|
|
||||||
return $this->errorValue->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var bool True if the result is `OK`, false if it is `Error` */
|
||||||
* Is this result `OK`?
|
public bool $isOK {
|
||||||
*
|
get => $this->okValue->isSome;
|
||||||
* @return bool True if the result is `OK`, false if it is `Error`
|
|
||||||
*/
|
|
||||||
public function isOK(): bool
|
|
||||||
{
|
|
||||||
return $this->okValue->isSome();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @var bool True if the result is `Error`, false if it is `OK` */
|
||||||
* Is this result `Error`?
|
public bool $isError {
|
||||||
*
|
get => $this->errorValue->isSome;
|
||||||
* @return bool True if the result is `Error`, false if it is `OK`
|
|
||||||
*/
|
|
||||||
public function isError(): bool
|
|
||||||
{
|
|
||||||
return $this->errorValue->isSome();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,7 +78,7 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function bind(callable $f): Result
|
public function bind(callable $f): Result
|
||||||
{
|
{
|
||||||
return $this->isError() ? $this : $f($this->getOK());
|
return $this->isError ? $this : $f($this->ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +91,7 @@ readonly class Result
|
||||||
public function contains(mixed $value, bool $strict = true): bool
|
public function contains(mixed $value, bool $strict = true): bool
|
||||||
{
|
{
|
||||||
return match (true) {
|
return match (true) {
|
||||||
$this->isError() => false,
|
$this->isError => false,
|
||||||
default => $this->okValue->contains($value, $strict),
|
default => $this->okValue->contains($value, $strict),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -126,7 +104,7 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function exists(callable $f): bool
|
public function exists(callable $f): bool
|
||||||
{
|
{
|
||||||
return $this->isOK() ? $f($this->okValue->get()) : false;
|
return $this->isOK ? $f($this->ok) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,7 +116,7 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function map(callable $f): self
|
public function map(callable $f): self
|
||||||
{
|
{
|
||||||
return $this->isOK() ? self::OK($f($this->getOK())) : $this;
|
return $this->isOK ? self::OK($f($this->ok)) : $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -150,7 +128,7 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function mapError(callable $f): self
|
public function mapError(callable $f): self
|
||||||
{
|
{
|
||||||
return $this->isError() ? self::Error($f($this->getError())) : $this;
|
return $this->isError ? self::Error($f($this->error)) : $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,8 +138,8 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function iter(callable $f): void
|
public function iter(callable $f): void
|
||||||
{
|
{
|
||||||
if ($this->isOK()) {
|
if ($this->isOK) {
|
||||||
$f($this->getOK());
|
$f($this->ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +160,7 @@ readonly class Result
|
||||||
*/
|
*/
|
||||||
public function toOption(): Option
|
public function toOption(): Option
|
||||||
{
|
{
|
||||||
return $this->isOK() ? Option::Some($this->getOK()) : Option::None();
|
return $this->isOK ? Option::Some($this->ok) : Option::None();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -20,43 +20,43 @@ use PHPUnit\Framework\TestCase;
|
||||||
*/
|
*/
|
||||||
class OptionTest extends TestCase
|
class OptionTest extends TestCase
|
||||||
{
|
{
|
||||||
#[TestDox('Get succeeds for Some')]
|
#[TestDox('Value succeeds for Some')]
|
||||||
public function testGetSucceedsForSome(): void
|
public function testValueSucceedsForSome(): void
|
||||||
{
|
{
|
||||||
$it = Option::Some(9);
|
$it = Option::Some(9);
|
||||||
$this->assertTrue($it->isSome(), 'The option should have been "Some"');
|
$this->assertTrue($it->isSome, 'The option should have been "Some"');
|
||||||
$this->assertEquals(9, $it->get(), 'The value was incorrect');
|
$this->assertEquals(9, $it->value, 'The value was incorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Get fails for None')]
|
#[TestDox('Value fails for None')]
|
||||||
public function testGetFailsForNone(): void
|
public function testValueFailsForNone(): void
|
||||||
{
|
{
|
||||||
$this->expectException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
Option::None()->get();
|
Option::None()->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsNone succeeds with None')]
|
#[TestDox('IsNone succeeds with None')]
|
||||||
public function testIsNoneSucceedsWithNone(): void
|
public function testIsNoneSucceedsWithNone(): void
|
||||||
{
|
{
|
||||||
$this->assertTrue(Option::None()->isNone(), '"None" should return true');
|
$this->assertTrue(Option::None()->isNone, '"None" should return true');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsNone succeeds with Some')]
|
#[TestDox('IsNone succeeds with Some')]
|
||||||
public function testIsNoneSucceedsWithSome(): void
|
public function testIsNoneSucceedsWithSome(): void
|
||||||
{
|
{
|
||||||
$this->assertFalse(Option::Some(8)->isNone(), '"Some" should return false');
|
$this->assertFalse(Option::Some(8)->isNone, '"Some" should return false');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsSome succeeds with None')]
|
#[TestDox('IsSome succeeds with None')]
|
||||||
public function testIsSomeSucceedsWithNone(): void
|
public function testIsSomeSucceedsWithNone(): void
|
||||||
{
|
{
|
||||||
$this->assertFalse(Option::None()->isSome(), '"None" should return false');
|
$this->assertFalse(Option::None()->isSome, '"None" should return false');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsSome succeeds with Some')]
|
#[TestDox('IsSome succeeds with Some')]
|
||||||
public function testIsSomeSucceedsWithSome(): void
|
public function testIsSomeSucceedsWithSome(): void
|
||||||
{
|
{
|
||||||
$this->assertTrue(Option::Some('boo')->isSome(), '"Some" should return true');
|
$this->assertTrue(Option::Some('boo')->isSome, '"Some" should return true');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('GetOrDefault succeeds with None')]
|
#[TestDox('GetOrDefault succeeds with None')]
|
||||||
|
@ -105,7 +105,7 @@ class OptionTest extends TestCase
|
||||||
{
|
{
|
||||||
$original = Option::None();
|
$original = Option::None();
|
||||||
$bound = $original->bind(fn($it) => Option::Some('value'));
|
$bound = $original->bind(fn($it) => Option::Some('value'));
|
||||||
$this->assertTrue($bound->isNone(), 'The option should have been None');
|
$this->assertTrue($bound->isNone, 'The option should have been None');
|
||||||
$this->assertSame($original, $bound, 'The same None instance should have been returned');
|
$this->assertSame($original, $bound, 'The same None instance should have been returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,15 +113,15 @@ class OptionTest extends TestCase
|
||||||
public function testBindSucceedsWithSomeAndSome(): void
|
public function testBindSucceedsWithSomeAndSome(): void
|
||||||
{
|
{
|
||||||
$bound = Option::Some('hello')->bind(fn($it) => Option::Some('goodbye'));
|
$bound = Option::Some('hello')->bind(fn($it) => Option::Some('goodbye'));
|
||||||
$this->assertTrue($bound->isSome(), 'The option should have been Some');
|
$this->assertTrue($bound->isSome, 'The option should have been Some');
|
||||||
$this->assertEquals('goodbye', $bound->get(), 'The bound function was not called');
|
$this->assertEquals('goodbye', $bound->value, 'The bound function was not called');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Bind succeeds with Some and None')]
|
#[TestDox('Bind succeeds with Some and None')]
|
||||||
public function testBindSucceedsWithSomeAndNone(): void
|
public function testBindSucceedsWithSomeAndNone(): void
|
||||||
{
|
{
|
||||||
$bound = Option::Some('greetings')->bind(fn($it) => Option::None());
|
$bound = Option::Some('greetings')->bind(fn($it) => Option::None());
|
||||||
$this->assertTrue($bound->isNone(), 'The option should have been None');
|
$this->assertTrue($bound->isNone, 'The option should have been None');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Contains succeeds with None')]
|
#[TestDox('Contains succeeds with None')]
|
||||||
|
@ -182,7 +182,7 @@ class OptionTest extends TestCase
|
||||||
$tattle->called = true;
|
$tattle->called = true;
|
||||||
return 'hello';
|
return 'hello';
|
||||||
});
|
});
|
||||||
$this->assertTrue($mapped->isNone(), 'The mapped option should be "None"');
|
$this->assertTrue($mapped->isNone, 'The mapped option should be "None"');
|
||||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||||
$this->assertSame($none, $mapped, 'The same "None" instance should have been returned');
|
$this->assertSame($none, $mapped, 'The same "None" instance should have been returned');
|
||||||
}
|
}
|
||||||
|
@ -191,8 +191,8 @@ class OptionTest extends TestCase
|
||||||
public function testMapSucceedsWithSome(): void
|
public function testMapSucceedsWithSome(): void
|
||||||
{
|
{
|
||||||
$mapped = Option::Some('abc ')->map(fn($it) => str_repeat($it, 2));
|
$mapped = Option::Some('abc ')->map(fn($it) => str_repeat($it, 2));
|
||||||
$this->assertTrue($mapped->isSome(), 'The mapped option should be "Some"');
|
$this->assertTrue($mapped->isSome, 'The mapped option should be "Some"');
|
||||||
$this->assertEquals('abc abc ', $mapped->get(), 'The mapping function was not called correctly');
|
$this->assertEquals('abc abc ', $mapped->value, 'The mapping function was not called correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Map fails with Some when mapping is null')]
|
#[TestDox('Map fails with Some when mapping is null')]
|
||||||
|
@ -228,7 +228,7 @@ class OptionTest extends TestCase
|
||||||
$tattle->called = true;
|
$tattle->called = true;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
$this->assertTrue($filtered->isNone(), 'The filtered option should have been "None"');
|
$this->assertTrue($filtered->isNone, 'The filtered option should have been "None"');
|
||||||
$this->assertFalse($tattle->called, 'The callable should not have been called');
|
$this->assertFalse($tattle->called, 'The callable should not have been called');
|
||||||
$this->assertSame($none, $filtered, 'The "None" instance returned should have been the one passed');
|
$this->assertSame($none, $filtered, 'The "None" instance returned should have been the one passed');
|
||||||
}
|
}
|
||||||
|
@ -238,8 +238,8 @@ class OptionTest extends TestCase
|
||||||
{
|
{
|
||||||
$some = Option::Some(12);
|
$some = Option::Some(12);
|
||||||
$filtered = $some->filter(fn($it) => $it % 2 === 0);
|
$filtered = $some->filter(fn($it) => $it % 2 === 0);
|
||||||
$this->assertTrue($filtered->isSome(), 'The filtered option should have been "Some"');
|
$this->assertTrue($filtered->isSome, 'The filtered option should have been "Some"');
|
||||||
$this->assertEquals(12, $filtered->get(), 'The filtered option value is incorrect');
|
$this->assertEquals(12, $filtered->value, 'The filtered option value is incorrect');
|
||||||
$this->assertSame($some, $filtered, 'The same "Some" instance should have been returned');
|
$this->assertSame($some, $filtered, 'The same "Some" instance should have been returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +248,7 @@ class OptionTest extends TestCase
|
||||||
{
|
{
|
||||||
$some = Option::Some(23);
|
$some = Option::Some(23);
|
||||||
$filtered = $some->filter(fn($it) => $it % 2 === 0);
|
$filtered = $some->filter(fn($it) => $it % 2 === 0);
|
||||||
$this->assertTrue($filtered->isNone(), 'The filtered option should have been "None"');
|
$this->assertTrue($filtered->isNone, 'The filtered option should have been "None"');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Unwrap succeeds with None')]
|
#[TestDox('Unwrap succeeds with None')]
|
||||||
|
@ -269,7 +269,7 @@ class OptionTest extends TestCase
|
||||||
$value = '';
|
$value = '';
|
||||||
$original = Option::Some('testing');
|
$original = Option::Some('testing');
|
||||||
$tapped = $original->tap(
|
$tapped = $original->tap(
|
||||||
function (Option $it) use (&$value) { $value = $it->isSome() ? $it->get() : 'none'; });
|
function (Option $it) use (&$value) { $value = $it->isSome ? $it->value : 'none'; });
|
||||||
$this->assertEquals('testing', $value, 'The tapped function was not called');
|
$this->assertEquals('testing', $value, 'The tapped function was not called');
|
||||||
$this->assertSame($original, $tapped, 'The same option should have been returned');
|
$this->assertSame($original, $tapped, 'The same option should have been returned');
|
||||||
}
|
}
|
||||||
|
@ -280,7 +280,7 @@ class OptionTest extends TestCase
|
||||||
$value = '';
|
$value = '';
|
||||||
$original = Option::None();
|
$original = Option::None();
|
||||||
$tapped = $original->tap(
|
$tapped = $original->tap(
|
||||||
function (Option $it) use (&$value) { $value = $it->isSome() ? $it->get() : 'none'; });
|
function (Option $it) use (&$value) { $value = $it->isSome ? $it->value : 'none'; });
|
||||||
$this->assertEquals('none', $value, 'The tapped function was not called');
|
$this->assertEquals('none', $value, 'The tapped function was not called');
|
||||||
$this->assertSame($original, $tapped, 'The same option should have been returned');
|
$this->assertSame($original, $tapped, 'The same option should have been returned');
|
||||||
}
|
}
|
||||||
|
@ -323,7 +323,7 @@ class OptionTest extends TestCase
|
||||||
public function testSomeSucceedsWithValue(): void
|
public function testSomeSucceedsWithValue(): void
|
||||||
{
|
{
|
||||||
$it = Option::Some('hello');
|
$it = Option::Some('hello');
|
||||||
$this->assertTrue($it->isSome(), 'The option should have been "Some"');
|
$this->assertTrue($it->isSome, 'The option should have been "Some"');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSomeFailsWithNull(): void
|
public function testSomeFailsWithNull(): void
|
||||||
|
@ -335,34 +335,34 @@ class OptionTest extends TestCase
|
||||||
public function testNoneSucceeds(): void
|
public function testNoneSucceeds(): void
|
||||||
{
|
{
|
||||||
$it = Option::None();
|
$it = Option::None();
|
||||||
$this->assertTrue($it->isNone(), 'The option should have been "None"');
|
$this->assertTrue($it->isNone, 'The option should have been "None"');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOfSucceedsWithNull(): void
|
public function testOfSucceedsWithNull(): void
|
||||||
{
|
{
|
||||||
$it = Option::of(null);
|
$it = Option::of(null);
|
||||||
$this->assertTrue($it->isNone(), '"null" should have created a "None" option');
|
$this->assertTrue($it->isNone, '"null" should have created a "None" option');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testOfSucceedsWithNonNull(): void
|
public function testOfSucceedsWithNonNull(): void
|
||||||
{
|
{
|
||||||
$it = Option::of('test');
|
$it = Option::of('test');
|
||||||
$this->assertTrue($it->isSome(), 'A non-null value should have created a "Some" option');
|
$this->assertTrue($it->isSome, 'A non-null value should have created a "Some" option');
|
||||||
$this->assertEquals('test', $it->get(), 'The value was not assigned correctly');
|
$this->assertEquals('test', $it->value, 'The value was not assigned correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Of succeeds with PhpOption\Some')]
|
#[TestDox('Of succeeds with PhpOption\Some')]
|
||||||
public function testOfSucceedsWithPhpOptionSome(): void
|
public function testOfSucceedsWithPhpOptionSome(): void
|
||||||
{
|
{
|
||||||
$it = Option::of(Some::create('something'));
|
$it = Option::of(Some::create('something'));
|
||||||
$this->assertTrue($it->isSome(), 'A "Some" PhpOption should have created a "Some" option');
|
$this->assertTrue($it->isSome, 'A "Some" PhpOption should have created a "Some" option');
|
||||||
$this->assertEquals('something', $it->get(), 'The value was not assigned correctly');
|
$this->assertEquals('something', $it->value, 'The value was not assigned correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Of succeeds with PhpOption\None')]
|
#[TestDox('Of succeeds with PhpOption\None')]
|
||||||
public function testOfSucceedsWithPhpOptionNone(): void
|
public function testOfSucceedsWithPhpOptionNone(): void
|
||||||
{
|
{
|
||||||
$it = Option::of(None::create());
|
$it = Option::of(None::create());
|
||||||
$this->assertTrue($it->isNone(), 'A "None" PhpOption should have created a "None" option');
|
$this->assertTrue($it->isNone, 'A "None" PhpOption should have created a "None" option');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,76 +18,76 @@ use PHPUnit\Framework\TestCase;
|
||||||
*/
|
*/
|
||||||
class ResultTest extends TestCase
|
class ResultTest extends TestCase
|
||||||
{
|
{
|
||||||
#[TestDox('GetOK succeeds for OK result')]
|
#[TestDox('OK property succeeds for OK result')]
|
||||||
public function testGetOKSucceedsForOKResult(): void
|
public function testOKPropertySucceedsForOKResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('yay');
|
$result = Result::OK('yay');
|
||||||
$this->assertEquals('yay', $result->getOK(), 'The OK result should have been returned');
|
$this->assertEquals('yay', $result->ok, 'The OK result should have been returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('GetOK fails for Error result')]
|
#[TestDox('OK property fails for Error result')]
|
||||||
public function testGetOKFailsForErrorResult(): void
|
public function testOKPropertyFailsForErrorResult(): void
|
||||||
{
|
{
|
||||||
$this->expectException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
Result::Error('whoops')->getOK();
|
Result::Error('whoops')->ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('GetError succeeds for Error result')]
|
#[TestDox('Error property succeeds for Error result')]
|
||||||
public function testGetErrorSucceedsForErrorResult(): void
|
public function testErrorPropertySucceedsForErrorResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::Error('boo');
|
$result = Result::Error('boo');
|
||||||
$this->assertEquals('boo', $result->getError(), 'The Error result should have been returned');
|
$this->assertEquals('boo', $result->error, 'The Error result should have been returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('GetError fails for OK result')]
|
#[TestDox('Error property fails for OK result')]
|
||||||
public function testGetErrorFailsForOKResult(): void
|
public function testErrorPropertyFailsForOKResult(): void
|
||||||
{
|
{
|
||||||
$this->expectException(InvalidArgumentException::class);
|
$this->expectException(InvalidArgumentException::class);
|
||||||
Result::OK('yeah')->getError();
|
Result::OK('yeah')->error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsOK succeeds for OK result')]
|
#[TestDox('IsOK succeeds for OK result')]
|
||||||
public function testIsOKSucceedsForOKResult(): void
|
public function testIsOKSucceedsForOKResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('ok');
|
$result = Result::OK('ok');
|
||||||
$this->assertTrue($result->isOK(), 'The check for "OK" should have returned true');
|
$this->assertTrue($result->isOK, 'The check for "OK" should have returned true');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsOK succeeds for Error result')]
|
#[TestDox('IsOK succeeds for Error result')]
|
||||||
public function testIsOKSucceedsForErrorResult(): void
|
public function testIsOKSucceedsForErrorResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::Error('error');
|
$result = Result::Error('error');
|
||||||
$this->assertFalse($result->isOK(), 'The check for "OK" should have returned false');
|
$this->assertFalse($result->isOK, 'The check for "OK" should have returned false');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsError succeeds for Error result')]
|
#[TestDox('IsError succeeds for Error result')]
|
||||||
public function testIsErrorSucceedsForErrorResult(): void
|
public function testIsErrorSucceedsForErrorResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::Error('not ok');
|
$result = Result::Error('not ok');
|
||||||
$this->assertTrue($result->isError(), 'The check for "Error" should have returned true');
|
$this->assertTrue($result->isError, 'The check for "Error" should have returned true');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('IsError succeeds for OK result')]
|
#[TestDox('IsError succeeds for OK result')]
|
||||||
public function testIsErrorSucceedsForOKResult(): void
|
public function testIsErrorSucceedsForOKResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('fine');
|
$result = Result::OK('fine');
|
||||||
$this->assertFalse($result->isError(), 'The check for "Error" should have returned false');
|
$this->assertFalse($result->isError, 'The check for "Error" should have returned false');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Bind succeeds for OK with OK')]
|
#[TestDox('Bind succeeds for OK with OK')]
|
||||||
public function testBindSucceedsForOKWithOK(): void
|
public function testBindSucceedsForOKWithOK(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('one')->bind(fn($it) => Result::OK("$it two"));
|
$result = Result::OK('one')->bind(fn($it) => Result::OK("$it two"));
|
||||||
$this->assertTrue($result->isOK(), 'The result should have been OK');
|
$this->assertTrue($result->isOK, 'The result should have been OK');
|
||||||
$this->assertEquals('one two', $result->getOK(), 'The bound function was not called');
|
$this->assertEquals('one two', $result->ok, 'The bound function was not called');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Bind succeeds for OK with Error')]
|
#[TestDox('Bind succeeds for OK with Error')]
|
||||||
public function testBindSucceedsForOKWithError(): void
|
public function testBindSucceedsForOKWithError(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('three')->bind(fn($it) => Result::Error('back to two'));
|
$result = Result::OK('three')->bind(fn($it) => Result::Error('back to two'));
|
||||||
$this->assertTrue($result->isError(), 'The result should have been Error');
|
$this->assertTrue($result->isError, 'The result should have been Error');
|
||||||
$this->assertEquals('back to two', $result->getError(), 'The bound function was not called');
|
$this->assertEquals('back to two', $result->error, 'The bound function was not called');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Bind succeeds for Error')]
|
#[TestDox('Bind succeeds for Error')]
|
||||||
|
@ -95,7 +95,7 @@ class ResultTest extends TestCase
|
||||||
{
|
{
|
||||||
$original = Result::Error('oops');
|
$original = Result::Error('oops');
|
||||||
$result = $original->bind(fn($it) => Result::OK('never mind - it worked!'));
|
$result = $original->bind(fn($it) => Result::OK('never mind - it worked!'));
|
||||||
$this->assertTrue($result->isError(), 'The result should have been Error');
|
$this->assertTrue($result->isError, 'The result should have been Error');
|
||||||
$this->assertSame($original, $result, 'The same Error result should have been returned');
|
$this->assertSame($original, $result, 'The same Error result should have been returned');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,8 +153,8 @@ class ResultTest extends TestCase
|
||||||
{
|
{
|
||||||
$ok = Result::OK('yard');
|
$ok = Result::OK('yard');
|
||||||
$mapped = $ok->map(fn($it) => strrev($it));
|
$mapped = $ok->map(fn($it) => strrev($it));
|
||||||
$this->assertTrue($mapped->isOK(), 'The mapped result should be "OK"');
|
$this->assertTrue($mapped->isOK, 'The mapped result should be "OK"');
|
||||||
$this->assertEquals('dray', $mapped->getOK(), 'The mapping function was not called correctly');
|
$this->assertEquals('dray', $mapped->ok, 'The mapping function was not called correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Map fails for OK result when mapping is null')]
|
#[TestDox('Map fails for OK result when mapping is null')]
|
||||||
|
@ -174,7 +174,7 @@ class ResultTest extends TestCase
|
||||||
$tattle->called = true;
|
$tattle->called = true;
|
||||||
return 'hello';
|
return 'hello';
|
||||||
});
|
});
|
||||||
$this->assertTrue($mapped->isError(), 'The mapped result should be "Error"');
|
$this->assertTrue($mapped->isError, 'The mapped result should be "Error"');
|
||||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||||
$this->assertSame($error, $mapped, 'The same "Error" instance should have been returned');
|
$this->assertSame($error, $mapped, 'The same "Error" instance should have been returned');
|
||||||
}
|
}
|
||||||
|
@ -189,7 +189,7 @@ class ResultTest extends TestCase
|
||||||
$tattle->called = true;
|
$tattle->called = true;
|
||||||
return 'hello';
|
return 'hello';
|
||||||
});
|
});
|
||||||
$this->assertTrue($mapped->isOK(), 'The mapped result should be "OK"');
|
$this->assertTrue($mapped->isOK, 'The mapped result should be "OK"');
|
||||||
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
$this->assertFalse($tattle->called, 'The mapping function should not have been called');
|
||||||
$this->assertSame($ok, $mapped, 'The same "OK" instance should have been returned');
|
$this->assertSame($ok, $mapped, 'The same "OK" instance should have been returned');
|
||||||
}
|
}
|
||||||
|
@ -199,8 +199,8 @@ class ResultTest extends TestCase
|
||||||
{
|
{
|
||||||
$error = Result::Error('taco');
|
$error = Result::Error('taco');
|
||||||
$mapped = $error->mapError(fn($it) => str_repeat('*', strlen($it)));
|
$mapped = $error->mapError(fn($it) => str_repeat('*', strlen($it)));
|
||||||
$this->assertTrue($mapped->isError(), 'The mapped result should be "Error"');
|
$this->assertTrue($mapped->isError, 'The mapped result should be "Error"');
|
||||||
$this->assertEquals('****', $mapped->getError(), 'The mapping function was not called correctly');
|
$this->assertEquals('****', $mapped->error, 'The mapping function was not called correctly');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('MapError fails for Error result when mapping is null')]
|
#[TestDox('MapError fails for Error result when mapping is null')]
|
||||||
|
@ -246,15 +246,15 @@ class ResultTest extends TestCase
|
||||||
public function testToOptionSucceedsForOKResult()
|
public function testToOptionSucceedsForOKResult()
|
||||||
{
|
{
|
||||||
$value = Result::OK(99)->toOption();
|
$value = Result::OK(99)->toOption();
|
||||||
$this->assertTrue($value->isSome(), 'An "OK" result should map to a "Some" option');
|
$this->assertTrue($value->isSome, 'An "OK" result should map to a "Some" option');
|
||||||
$this->assertEquals(99, $value->get(), 'The value is not correct');
|
$this->assertEquals(99, $value->value, 'The value is not correct');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('ToOption succeeds for Error result')]
|
#[TestDox('ToOption succeeds for Error result')]
|
||||||
public function testToOptionSucceedsForErrorResult()
|
public function testToOptionSucceedsForErrorResult()
|
||||||
{
|
{
|
||||||
$value = Result::Error('file not found')->toOption();
|
$value = Result::Error('file not found')->toOption();
|
||||||
$this->assertTrue($value->isNone(), 'An "Error" result should map to a "None" option');
|
$this->assertTrue($value->isNone, 'An "Error" result should map to a "None" option');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Tap succeeds for OK result')]
|
#[TestDox('Tap succeeds for OK result')]
|
||||||
|
@ -263,7 +263,7 @@ class ResultTest extends TestCase
|
||||||
$value = '';
|
$value = '';
|
||||||
$original = Result::OK('working');
|
$original = Result::OK('working');
|
||||||
$tapped = $original->tap(function (Result $it) use (&$value) {
|
$tapped = $original->tap(function (Result $it) use (&$value) {
|
||||||
$value = $it->isOK() ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
$value = $it->isOK ? 'OK: ' . $it->ok : 'Error: ' . $it->error;
|
||||||
});
|
});
|
||||||
$this->assertEquals('OK: working', $value, 'The tapped function was not called');
|
$this->assertEquals('OK: working', $value, 'The tapped function was not called');
|
||||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||||
|
@ -275,7 +275,7 @@ class ResultTest extends TestCase
|
||||||
$value = '';
|
$value = '';
|
||||||
$original = Result::Error('failed');
|
$original = Result::Error('failed');
|
||||||
$tapped = $original->tap(function (Result $it) use (&$value) {
|
$tapped = $original->tap(function (Result $it) use (&$value) {
|
||||||
$value = $it->isOK() ? 'OK: ' . $it->getOK() : 'Error: ' . $it->getError();
|
$value = $it->isOK ? 'OK: ' . $it->ok : 'Error: ' . $it->error;
|
||||||
});
|
});
|
||||||
$this->assertEquals('Error: failed', $value, 'The tapped function was not called');
|
$this->assertEquals('Error: failed', $value, 'The tapped function was not called');
|
||||||
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
$this->assertSame($original, $tapped, 'The same result should have been returned');
|
||||||
|
@ -285,8 +285,8 @@ class ResultTest extends TestCase
|
||||||
public function testOKSucceedsForNonNullResult(): void
|
public function testOKSucceedsForNonNullResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::OK('something');
|
$result = Result::OK('something');
|
||||||
$this->assertTrue($result->isOK(), 'The result should have been "OK"');
|
$this->assertTrue($result->isOK, 'The result should have been "OK"');
|
||||||
$this->assertEquals('something', $result->getOK(), 'The "OK" value was incorrect');
|
$this->assertEquals('something', $result->ok, 'The "OK" value was incorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('OK fails for null result')]
|
#[TestDox('OK fails for null result')]
|
||||||
|
@ -300,8 +300,8 @@ class ResultTest extends TestCase
|
||||||
public function testErrorSucceedsForNonNullResult(): void
|
public function testErrorSucceedsForNonNullResult(): void
|
||||||
{
|
{
|
||||||
$result = Result::Error('sad trombone');
|
$result = Result::Error('sad trombone');
|
||||||
$this->assertTrue($result->isError(), 'The result should have been "Error"');
|
$this->assertTrue($result->isError, 'The result should have been "Error"');
|
||||||
$this->assertEquals('sad trombone', $result->getError(), 'The "Error" value was incorrect');
|
$this->assertEquals('sad trombone', $result->error, 'The "Error" value was incorrect');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[TestDox('Error fails for null result')]
|
#[TestDox('Error fails for null result')]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user