*/ abstract class Option implements IteratorAggregate { /** * @template S * * @param S $value * @param S $noneValue * * @return Option */ public static function fromValue($value, $noneValue = null) { if ($value === $noneValue) { return None::create(); } return new Some($value); } /** * @template S * * @param array|ArrayAccess|null $array * @param string|int|null $key * * @return Option */ public static function fromArraysValue($array, $key) { if ( $key === null || !(is_array($array) || $array instanceof ArrayAccess) || !isset($array[$key]) ) { return None::create(); } return new Some($array[$key]); } /** * @template S * * @param callable $callback * @param array $arguments * @param S $noneValue * * @return LazyOption */ public static function fromReturn( $callback, array $arguments = [], $noneValue = null, ) { return new LazyOption(static function () use ( $callback, $arguments, $noneValue, ) { /** @var mixed */ $return = call_user_func_array($callback, $arguments); if ($return === $noneValue) { return None::create(); } return new Some($return); }); } /** * @template S * * @param Option|callable|S $value * @param S $noneValue * * @return Option|LazyOption */ public static function ensure($value, $noneValue = null) { if ($value instanceof self) { return $value; } elseif (is_callable($value)) { return new LazyOption(static function () use ($value, $noneValue) { /** @var mixed */ $return = $value(); if ($return instanceof self) { return $return; } else { return self::fromValue($return, $noneValue); } }); } else { return self::fromValue($value, $noneValue); } } /** * @template S * * @param callable $callback * @param mixed $noneValue * * @return callable */ public static function lift($callback, $noneValue = null) { return static function () use ($callback, $noneValue) { /** @var array */ $args = func_get_args(); $reduced_args = array_reduce( $args, /** @param bool $status */ static function ($status, self $o) { return $o->isEmpty() ? true : $status; }, false, ); if ($reduced_args) { return None::create(); } $args = array_map(static function (self $o) { return $o->get(); }, $args); return self::ensure( call_user_func_array($callback, $args), $noneValue, ); }; } /** @return T */ abstract public function get(); /** * @template S * @param S $default * @return T|S */ abstract public function getOrElse($default); /** * @template S * @param callable():S $callable * @return T|S */ abstract public function getOrCall($callable); /** @return T */ abstract public function getOrThrow(Exception $ex); abstract public function isEmpty(): bool; abstract public function isDefined(): bool; /** * @param Option $else * @return Option */ abstract public function orElse(self $else); /** @deprecated Use forAll() instead. */ abstract public function ifDefined($callable); /** * @param callable(T):mixed $callable * @return Option */ abstract public function forAll($callable); /** * @template S * @param callable(T):S $callable * @return Option */ abstract public function map($callable); /** * @template S * @param callable(T):Option $callable * @return Option */ abstract public function flatMap($callable); /** * @param callable(T):bool $callable * @return Option */ abstract public function filter($callable); /** * @param callable(T):bool $callable * @return Option */ abstract public function filterNot($callable); /** * @param T $value * @return Option */ abstract public function select($value); /** * @param T $value * @return Option */ abstract public function reject($value); /** * @template S * @param S $initialValue * @param callable(S, T):S $callable * @return S */ abstract public function foldLeft($initialValue, $callable); /** * @template S * @param S $initialValue * @param callable(T, S):S $callable * @return S */ abstract public function foldRight($initialValue, $callable); }