diff --git a/README.md b/README.md index 70a3704..78db57a 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ It’s a game-changer! composer require yceruto/option-type ``` -## Usage (Handling the presence or absence of a value) +## Handling the presence or absence of a value Options are commonly paired with pattern matching to query the presence of a value and take action, always accounting for the `None` case. diff --git a/docs/api_reference.md b/docs/api_reference.md index 33fd9ae..e120bef 100644 --- a/docs/api_reference.md +++ b/docs/api_reference.md @@ -1,9 +1,48 @@ -## PHP `Option` Type Documentation +# PHP `Option` Type Documentation -The `Option` type in PHP is designed to handle the presence or absence of a value explicitly as part of its state. +The `Option` type in PHP is designed to handle the presence or absence of a value explicitly as part of its state. This allows developers to write more robust code by avoiding common errors like type errors and undefined indices. -### **`some(mixed $value): self`** +_Table of Contents:_ + +- Creating an Option + - [some](#optionsomemixed-value-self) + - [none](#optionnone-self) + - [from](#optionfrommixed-value-self) + - [clone](#optionclone-self) +- Querying the variant + - [isSome](#optionissome-bool) + - [isNone](#optionisnone-bool) +- Extracting the contained value + - [expect](#optionexpectstring-message-mixed) + - [unwrap](#optionunwrap-mixed) + - [unwrapOr](#optionunwrapormixed-default-mixed) + - [unwrapOrElse](#optionunwraporelsecallable-fn-mixed) + - [unwrapOrThrow](#optionunwraporthrowthrowable-error-mixed) + - [flatten](#optionflatten-self) +- Transforming contained values + - [match](#optionmatchcallable-some-callable-none-mixed) + - [map](#optionmapcallable-fn-self) + - [mapOr](#optionmaporcallable-fn-mixed-default-mixed) + - [mapOrElse](#optionmaporelsecallable-fn-callable-default-mixed) + - [andThen](#optionandthencallable-fn-self) + - [filter](#optionfiltercallable-predicate-self) +- Boolean operators + - [or](#optionorself-option-self) + - [orElse](#optionorelsecallable-fn-self) + - [xor](#optionxorself-option-self) + - [and](#optionandself-option-self) +- Iterating over `Option` + - [iterate](#optioniterate-arrayiterator) +- Comparison operators + - [equals](#optionequalsself-option-bool) +- Shortcut functions + - [some](#somemixed-value-option) + - [none](#none-option) + +## Creating an `Option` + +### **`Option::some(mixed $value): self`** Creates an `Option` instance containing a non-null value. If `null` is passed, a `LogicException` is thrown. @@ -14,7 +53,7 @@ echo $opt->unwrap(); // Outputs: 10 Option::some(null); // Throws LogicException ``` -### **`none(): self`** +### **`Option::none(): self`** Creates an `Option` instance representing the absence of a value (i.e., `None`). @@ -23,7 +62,7 @@ $opt = Option::none(); echo $opt->isNone(); // Outputs: true ``` -### **`from(mixed $value): self`** +### **`Option::from(mixed $value): self`** Converts a value to an `Option`, making it `None` if the original value is `null`, otherwise `Some`. @@ -34,7 +73,19 @@ echo $some->isSome(); // Outputs: true echo $none->isNone(); // Outputs: true ``` -### **`isSome(): bool`** +### **`Option::clone(): self`** + +Creates a copy of the option. Useful for preserving immutability when needed. + +```php +$x = Option::some(2); +$y = $x->clone(); +echo $y->unwrap(); // Outputs: 2 +``` + +## Querying the variant + +### **`Option::isSome(): bool`** Checks if the option is a `Some` value. @@ -43,7 +94,7 @@ $opt = Option::some(10); echo $opt->isSome(); // Outputs: true ``` -### **`isNone(): bool`** +### **`Option::isNone(): bool`** Checks if the option is a `None` value. @@ -52,25 +103,9 @@ $opt = Option::none(); echo $opt->isNone(); // Outputs: true ``` -### **`match(callable $some, callable $none): mixed`** - -Applies a function to the contained value if it is `Some`, otherwise applies another function. - -```php -$x = Option::some(2); -echo $x->match( - some: fn ($v) => $v * 2, - none: fn () => 0, -); // Outputs: 4 - -$x = Option::none(); -echo $x->match( - some: fn ($v) => $v * 2, - none: fn () => 0, -); // Outputs: 0 -``` +## Extracting the contained value -### **`expect(string $message): mixed`** +### **`Option::expect(string $message): mixed`** Returns the contained value if it is `Some`; otherwise, throws a `LogicException` with a custom message. @@ -82,7 +117,7 @@ $opt = Option::none(); echo $opt->expect('A number.'); // Throws LogicException with custom message ``` -### **`unwrap(): mixed`** +### **`Option::unwrap(): mixed`** Returns the contained value if it is `Some`; otherwise, throws a `LogicException`. @@ -94,7 +129,7 @@ $opt = Option::none(); echo $opt->unwrap(); // Throws LogicException ``` -### **`unwrapOr(mixed $default): mixed`** +### **`Option::unwrapOr(mixed $default): mixed`** Returns the contained value if it is `Some`; otherwise, returns a provided default value. @@ -106,7 +141,7 @@ $opt = Option::none(); echo $opt->unwrapOr(5); // Outputs: 5 ``` -### **`unwrapOrElse(callable $fn): mixed`** +### **`Option::unwrapOrElse(callable $fn): mixed`** Returns the contained value if it is `Some`; otherwise, computes a value using a provided callable. @@ -118,7 +153,7 @@ $opt = Option::none(); echo $opt->unwrapOrElse(fn () => 5); // Outputs: 5 ``` -### **`unwrapOrThrow(\Throwable $error): mixed`** +### **`Option::unwrapOrThrow(\Throwable $error): mixed`** Returns the contained value if it is `Some`; otherwise, throws the provided throwable error. @@ -130,7 +165,39 @@ $opt = Option::none(); echo $opt->unwrapOrThrow(new \Exception("No value!")); // Throws Exception ``` -### **`map(callable $fn): self`** +### **`Option::flatten(): self`** + +Converts from `Option>` to `Option`. Useful for unwrapping nested options. + +```php +$x = Option::some(Option::some(2)); +echo $x->flatten()->unwrap(); // Outputs: 2 + +$x = Option::some(Option::none()); +echo $x->flatten()->isNone(); // Outputs: true +``` + +## Transforming contained values + +### **`Option::match(callable $some, callable $none): mixed`** + +Applies a function to the contained value if it is `Some`, otherwise applies another function. + +```php +$x = Option::some(2); +echo $x->match( + some: fn ($v) => $v * 2, + none: fn () => 0, +); // Outputs: 4 + +$x = Option::none(); +echo $x->match( + some: fn ($v) => $v * 2, + none: fn () => 0, +); // Outputs: 0 +``` + +### **`Option::map(callable $fn): self`** Transforms the contained value by applying a function if it is `Some`; returns `None` if it is `None`. @@ -144,7 +211,7 @@ $result = $opt->map(fn ($x) => $x * 2); echo $result->isNone(); // Outputs: true ``` -### **`mapOr(callable $fn, mixed $default): mixed`** +### **`Option::mapOr(callable $fn, mixed $default): mixed`** Applies a function to the contained value if it is `Some`, otherwise returns a default value. @@ -156,7 +223,7 @@ $opt = Option::none(); echo $opt->mapOr(fn ($x) => $x * 2, 0); // Outputs: 0 ``` -### **`mapOrElse(callable $fn, callable $default): mixed`** +### **`Option::mapOrElse(callable $fn, callable $default): mixed`** Applies a function to the contained value if it is `Some`, otherwise computes the default using another callable. @@ -168,7 +235,38 @@ $opt = Option::none(); echo $opt->mapOrElse(fn ($x) => $x * 2, fn () => 0); // Outputs: 0 ``` -### **`or(self $option): self`** +### **`Option::andThen(callable $fn): self`** + +Applies a function to the contained value if it is `Some`, otherwise returns `None`. This is also known as flatmap +in other languages. + +```php +$x = Option::some(2); +$result = $x->andThen(fn ($value) => Option::some($value * 2)); +echo $result->unwrap(); // Outputs: 4 + +$x = Option::none(); +$result = $x->andThen(fn ($value) => Option::some($value * 2)); +echo $result->isNone(); // Outputs: true +``` + +### **`Option::filter(callable $predicate): self`** + +Returns `Some` if the option is `Some` and the predicate returns `true`; otherwise, returns `None`. + +```php +$isEven = fn ($x) => $x % 2 === 0; + +$x = Option::some(4); +echo $x->filter($isEven)->isSome(); // Outputs: true + +$x = Option::some(5); +echo $x->filter($isEven)->isNone(); // Outputs: true +``` + +## Boolean operators + +### **`Option::or(self $option): self`** Returns the option itself if it is `Some`, otherwise returns the provided option. @@ -181,7 +279,7 @@ $x = Option::none(); echo $x->or($y)->unwrap(); // Outputs: 3 ``` -### **`orElse(callable $fn): self`** +### **`Option::orElse(callable $fn): self`** Returns the option itself if it is `Some`, otherwise calls a callable to provide an option. @@ -194,7 +292,7 @@ $x = Option::none(); echo $x->orElse(fn () => $y)->unwrap(); // Outputs: 3 ``` -### **`xor(self $option): self`** +### **`Option::xor(self $option): self`** Returns `Some` if exactly one of the options is `Some`, otherwise returns `None`. @@ -207,7 +305,7 @@ $x = Option::none(); echo $x->xor($y)->unwrap(); // Outputs: 3 ``` -### **`and(self $option): self`** +### **`Option::and(self $option): self`** Returns the provided option if the original option is `Some`, otherwise returns `None`. @@ -220,22 +318,9 @@ $x = Option::none(); echo $x->and($y)->isNone(); // Outputs: true ``` -### **`andThen(callable $fn): self`** - -Applies a function to the contained value if it is `Some`, otherwise returns `None`. This is also known as flatmap -in other languages. - -```php -$x = Option::some(2); -$result = $x->andThen(fn ($value) => Option::some($value * 2)); -echo $result->unwrap(); // Outputs: 4 - -$x = Option::none(); -$result = $x->andThen(fn ($value) => Option::some($value * 2)); -echo $result->isNone(); // Outputs: true -``` +## Iterating over `Option` -### **`iterate(): \ArrayIterator`** +### **`Option::iterate(): \ArrayIterator`** Provides an iterator over the contained value if it is `Some`, otherwise an empty iterator. @@ -251,21 +336,9 @@ foreach ($x->iterate() as $v) { } ``` -### **`filter(callable $predicate): self`** +## Comparison operators -Returns `Some` if the option is `Some` and the predicate returns `true`; otherwise, returns `None`. - -```php -$isEven = fn ($x) => $x % 2 === 0; - -$x = Option::some(4); -echo $x->filter($isEven)->isSome(); // Outputs: true - -$x = Option::some(5); -echo $x->filter($isEven)->isNone(); // Outputs: true -``` - -### **`equals(self $option): bool`** +### **`Option::equals(self $option): bool`** Compares two options for equality. Returns `true` if both are `None` or if both are `Some` with equal values. @@ -279,28 +352,6 @@ $y = Option::none(); echo $x->equals($y); // Outputs: true ``` -### **`flatten(): self`** - -Converts from `Option>` to `Option`. Useful for unwrapping nested options. - -```php -$x = Option::some(Option::some(2)); -echo $x->flatten()->unwrap(); // Outputs: 2 - -$x = Option::some(Option::none()); -echo $x->flatten()->isNone(); // Outputs: true -``` - -### **`clone(): self`** - -Creates a copy of the option. Useful for preserving immutability when needed. - -```php -$x = Option::some(2); -$y = $x->clone(); -echo $y->unwrap(); // Outputs: 2 -``` - ## Shortcut Functions ### **`some(mixed $value): Option`**