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 false $this->isSome()
48: * @phpstan-assert-if-false true $this->isSome()
49: */
50: public function isNone(): bool;
51:
52: /**
53: * Returns the contained **Some** value, consuming the `self` value.
54: *
55: * Because this method may throw, its use is generally discouraged.
56: * Instead, prefer to call `Option::unwrapOr()` or `Option::unwrapOrElse()`.
57: *
58: * @return T
59: *
60: * @throws NoneException
61: */
62: public function unwrap(): mixed;
63:
64: /**
65: * Returns the contained **Some** value or a provided default.
66: *
67: * Arguments passed to `Option::unwrapOr()` are eagerly evaluated; if you are
68: * passing the result of a function call, it is recommended to use `Option::unwrapOrElse()`,
69: * which is lazily evaluated.
70: *
71: * @template S
72: *
73: * @param S $default
74: *
75: * @return S|T
76: */
77: public function unwrapOr(mixed $default): mixed;
78:
79: /**
80: * Returns the contained **Some** value or computes it from a closure.
81: *
82: * @template S
83: *
84: * @param (\Closure(): S) $default
85: *
86: * @return S|T
87: */
88: public function unwrapOrElse(\Closure $default): mixed;
89:
90: /**
91: * Maps an `Option<T>` to `Option<U>` by applying a function to a
92: * contained value (if **Some**) or returns `None` (if **None**).
93: *
94: * @template U
95: *
96: * @param (\Closure(T): U) $predicate
97: *
98: * @return self<U>
99: */
100: public function map(\Closure $predicate): self;
101:
102: /**
103: * Returns the provided default result (if none), or applies a function
104: * to the contained value (if any).
105: *
106: * Arguments passed to `Option::mapOr()` are eagerly evaluated; if you are
107: * passing the result of a function call, it is recommended to use `Option::mapOrElse()`,
108: * which is lazily evaluated.
109: *
110: * @template U
111: * @template V
112: *
113: * @param V $default
114: * @param (\Closure(T): U) $predicate
115: *
116: * @return U|V
117: */
118: public function mapOr(mixed $default, \Closure $predicate): mixed;
119:
120: /**
121: * Computes a default function result (if none), or applies a different function
122: * to the contained value (if any).
123: *
124: * @template U
125: * @template V
126: *
127: * @param (\Closure(): V) $default
128: * @param (\Closure(T): U) $predicate
129: *
130: * @return U|V
131: */
132: public function mapOrElse(\Closure $default, \Closure $predicate): mixed;
133:
134: /**
135: * Returns **None** if the option is **None**, otherwise returns `$other`.
136: *
137: * Arguments passed to `Option::and()` are eagerly evaluated; if you are
138: * passing the result of a function call, it is recommended to use `Option::andThen()`,
139: * which is lazily evaluated.
140: *
141: * @template U of Option
142: *
143: * @param U $other
144: *
145: * @return U
146: */
147: public function and(self $other): self;
148:
149: /**
150: * Returns **None** if the option is **None**, otherwise calls `$other` with the wrapped
151: * value and returns the result.
152: *
153: * @template U of Option
154: *
155: * @param (\Closure(T): U) $predicate
156: *
157: * @return U
158: */
159: public function andThen(\Closure $predicate): self;
160:
161: /**
162: * Returns **None** if the option is **None**, otherwise calls `$predicate`
163: * with the wrapped value and returns:
164: * - `Some(t)` if predicate returns true (where `t` is the wrapped value), and
165: * - `None` if predicate returns false.
166: *
167: * @param (\Closure(T): bool) $predicate
168: *
169: * @return self<T>
170: */
171: public function filter(\Closure $predicate): self;
172:
173: /**
174: * Returns the option if it contains a value, otherwise returns `$other`.
175: *
176: * Arguments passed to `Option::or()` are eagerly evaluated; if you are
177: * passing the result of a function call, it is recommended to use `Option::orElse()`,
178: * which is lazily evaluated.
179: *
180: * @template S of Option
181: *
182: * @param S $other
183: *
184: * @return S
185: */
186: public function or(self $other): self;
187:
188: /**
189: * Returns the option if it contains a value, otherwise calls
190: * `$other` and returns the result.
191: *
192: * @template S of Option
193: *
194: * @param (\Closure(): S) $other
195: *
196: * @return S
197: */
198: public function orElse(\Closure $other): self;
199:
200: /**
201: * Returns **Some** if exactly one of `self`, `$other` is **Some**, otherwise returns **None**.
202: *
203: * @template S
204: *
205: * @param self<S> $other
206: *
207: * @return self<S>
208: */
209: public function xor(self $other): self;
210: }
211: