1: <?php
2:
3: declare(strict_types=1);
4:
5: /**
6: * This file is part of the Nexus framework.
7: *
8: * (c) John Paul E. Balandan, CPA <paulbalandan@gmail.com>
9: *
10: * For the full copyright and license information, please view
11: * the LICENSE file that was distributed with this source code.
12: */
13:
14: namespace Nexus\Option;
15:
16: /**
17: * A PHP implementation of Rust's Option enum.
18: *
19: * @see https://doc.rust-lang.org/std/option/enum.Option.html
20: *
21: * @template T
22: *
23: * @extends \IteratorAggregate<int, T>
24: */
25: interface Option extends \IteratorAggregate
26: {
27: /**
28: * Returns `true` if the option is a **Some** value.
29: *
30: * @phpstan-assert-if-true Some<T> $this
31: * @phpstan-assert-if-true false $this->isNone()
32: * @phpstan-assert-if-false None $this
33: * @phpstan-assert-if-false true $this->isNone()
34: */
35: public function isSome(): bool;
36:
37: /**
38: * Returns `true` if the option is a **Some** and the value inside of it matches a predicate.
39: *
40: * @param (\Closure(T): bool) $predicate
41: */
42: public function isSomeAnd(\Closure $predicate): bool;
43:
44: /**
45: * Returns `true` if the option is a **None** value.
46: *
47: * @phpstan-assert-if-true None $this
48: * @phpstan-assert-if-true false $this->isSome()
49: * @phpstan-assert-if-false Some<T> $this
50: * @phpstan-assert-if-false true $this->isSome()
51: */
52: public function isNone(): bool;
53:
54: /**
55: * Returns the contained **Some** value, consuming the `self` value.
56: *
57: * Because this method may throw, its use is generally discouraged.
58: * Instead, prefer to call `Option::unwrapOr()` or `Option::unwrapOrElse()`.
59: *
60: * @return T
61: *
62: * @throws NoneException
63: */
64: public function unwrap(): mixed;
65:
66: /**
67: * Returns the contained **Some** value or a provided default.
68: *
69: * Arguments passed to `Option::unwrapOr()` are eagerly evaluated; if you are
70: * passing the result of a function call, it is recommended to use `Option::unwrapOrElse()`,
71: * which is lazily evaluated.
72: *
73: * @template S
74: *
75: * @param S $default
76: *
77: * @return S|T
78: */
79: public function unwrapOr(mixed $default): mixed;
80:
81: /**
82: * Returns the contained **Some** value or computes it from a closure.
83: *
84: * @template S
85: *
86: * @param (\Closure(): S) $default
87: *
88: * @return S|T
89: */
90: public function unwrapOrElse(\Closure $default): mixed;
91:
92: /**
93: * Maps an `Option<T>` to `Option<U>` by applying a function to a
94: * contained value (if **Some**) or returns `None` (if **None**).
95: *
96: * @template U
97: *
98: * @param (\Closure(T): U) $predicate
99: *
100: * @return self<U>
101: */
102: public function map(\Closure $predicate): self;
103:
104: /**
105: * Returns the provided default result (if none), or applies a function
106: * to the contained value (if any).
107: *
108: * Arguments passed to `Option::mapOr()` are eagerly evaluated; if you are
109: * passing the result of a function call, it is recommended to use `Option::mapOrElse()`,
110: * which is lazily evaluated.
111: *
112: * @template U
113: * @template V
114: *
115: * @param V $default
116: * @param (\Closure(T): U) $predicate
117: *
118: * @return U|V
119: */
120: public function mapOr(mixed $default, \Closure $predicate): mixed;
121:
122: /**
123: * Computes a default function result (if none), or applies a different function
124: * to the contained value (if any).
125: *
126: * @template U
127: * @template V
128: *
129: * @param (\Closure(): V) $default
130: * @param (\Closure(T): U) $predicate
131: *
132: * @return U|V
133: */
134: public function mapOrElse(\Closure $default, \Closure $predicate): mixed;
135:
136: /**
137: * Returns **None** if the option is **None**, otherwise returns `$other`.
138: *
139: * Arguments passed to `Option::and()` are eagerly evaluated; if you are
140: * passing the result of a function call, it is recommended to use `Option::andThen()`,
141: * which is lazily evaluated.
142: *
143: * @template U of Option
144: *
145: * @param U $other
146: *
147: * @return U
148: */
149: public function and(self $other): self;
150:
151: /**
152: * Returns **None** if the option is **None**, otherwise calls `$other` with the wrapped
153: * value and returns the result.
154: *
155: * @template U of Option
156: *
157: * @param (\Closure(T): U) $predicate
158: *
159: * @return U
160: */
161: public function andThen(\Closure $predicate): self;
162:
163: /**
164: * Returns **None** if the option is **None**, otherwise calls `$predicate`
165: * with the wrapped value and returns:
166: * - `Some(t)` if predicate returns true (where `t` is the wrapped value), and
167: * - `None` if predicate returns false.
168: *
169: * @param (\Closure(T): bool) $predicate
170: *
171: * @return self<T>
172: */
173: public function filter(\Closure $predicate): self;
174:
175: /**
176: * Returns the option if it contains a value, otherwise returns `$other`.
177: *
178: * Arguments passed to `Option::or()` are eagerly evaluated; if you are
179: * passing the result of a function call, it is recommended to use `Option::orElse()`,
180: * which is lazily evaluated.
181: *
182: * @template S of Option
183: *
184: * @param S $other
185: *
186: * @return S
187: */
188: public function or(self $other): self;
189:
190: /**
191: * Returns the option if it contains a value, otherwise calls
192: * `$other` and returns the result.
193: *
194: * @template S of Option
195: *
196: * @param (\Closure(): S) $other
197: *
198: * @return S
199: */
200: public function orElse(\Closure $other): self;
201:
202: /**
203: * Returns **Some** if exactly one of `self`, `$other` is **Some**, otherwise returns **None**.
204: *
205: * @template S
206: *
207: * @param self<S> $other
208: *
209: * @return self<S>
210: */
211: public function xor(self $other): self;
212: }
213: