66use RuntimeException ;
77use Throwable ;
88use Toolkit \Stdlib \Obj ;
9+ use Toolkit \Stdlib \Util \Stream \DataStream ;
910use UnexpectedValueException ;
1011use function gettype ;
1112
1213/**
13- * class Optional
14+ * class Optional - like java: java.util.Optional
1415 *
1516 * @template T
1617 *
@@ -22,7 +23,7 @@ final class Optional
2223 /**
2324 * @var self|null
2425 */
25- private static ?Optional $ empty ;
26+ private static ?Optional $ empty = null ;
2627
2728 /**
2829 * Returns an Optional with the specified present non-null value.
@@ -136,7 +137,15 @@ public function get()
136137 */
137138 public function isNull (): bool
138139 {
139- return $ this ->value !== null ;
140+ return $ this ->value === null ;
141+ }
142+
143+ /**
144+ * @return bool
145+ */
146+ public function isEmpty (): bool
147+ {
148+ return $ this ->value === null ;
140149 }
141150
142151 /**
@@ -179,7 +188,7 @@ public function filter(callable $checker): self
179188 /**
180189 * If a value is present, apply the provided mapping function to it,
181190 * and if the result is non-null, return an Optional describing the result.
182- * Otherwise return an empty Optional
191+ * Otherwise, return an empty Optional
183192 *
184193 * ```php
185194 * Optional::of("foo")->map('strtoupper')->get(); // "FOO"
@@ -227,12 +236,46 @@ public function flatMap(callable $flatMapper): self
227236 return $ new ;
228237 }
229238
239+ /**
240+ * @param callable():Optional<T> $supplier
241+ *
242+ * @return $this
243+ */
244+ public function or (callable $ supplier ): self
245+ {
246+ if ($ this ->isPresent ()) {
247+ return $ this ;
248+ }
249+
250+ $ new = $ supplier ();
251+ if (!$ new instanceof self) {
252+ throw new UnexpectedValueException ('must return an object and instance of ' . self ::class);
253+ }
254+
255+ return $ new ;
256+ }
257+
258+ /**
259+ * If a value is present, returns a sequential Stream containing only that value,
260+ * otherwise returns an empty Stream.
261+ *
262+ * @return DataStream<T>
263+ */
264+ public function stream (): DataStream
265+ {
266+ if (!$ this ->isPresent ()) {
267+ return DataStream::empty ();
268+ }
269+
270+ return DataStream::of ($ this ->value );
271+ }
272+
230273 /**
231274 * @param T $other
232275 *
233276 * @return T
234277 */
235- public function orElse ($ other )
278+ public function orElse (mixed $ other )
236279 {
237280 return $ this ->value ?? $ other ;
238281 }
@@ -248,17 +291,21 @@ public function orElseGet(callable $valCreator)
248291 }
249292
250293 /**
251- * @param callable(): Throwable $errCreator
294+ * @param null| callable():Throwable $errCreator
252295 *
253296 * @return T
254297 */
255- public function orElseThrow (callable $ errCreator )
298+ public function orElseThrow (callable $ errCreator = null )
256299 {
257300 if ($ this ->value !== null ) {
258301 return $ this ->value ;
259302 }
260303
261- throw $ errCreator ();
304+ if ($ errCreator ) {
305+ throw $ errCreator ();
306+ }
307+
308+ throw new UnexpectedValueException ('No value present ' );
262309 }
263310
264311 /**
0 commit comments