Re: Consensus Gathering: is_initialized
| From: | Larry Garfield | Date: | Thu, 27 May 2021 22:52:57 +0000 |
| Subject: | Re: Consensus Gathering: is_initialized | ||
| References: | 1 2 3 4 5 6 7 8 9 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-114652@lists.php.net to get a copy of this message | ||
On Thu, May 27, 2021, at 8:23 AM, Rowan Tommins wrote:
> The combination of union types and enums actually gives a much more
> expressive way of representing "valid value or explicit null or special
> default". To use the ORM lazy-loading example:
>
>
> enum ORMState {
> case Unloaded;
> }
>
> class Example {
> private int|ORMState|null $foo = ORMState::Unloaded;
>
> public function getFoo(): ?int {
> if ( $this->foo === ORMState::Unloaded ) {
> $this->foo = $this->loadFromDatabase('foo');
> }
> return $this->foo;
> }
>
> private function loadFromDatabase($fieldName): ?int {
> echo "Fetching '$fieldName' from database...\n";
> return 42;
> }
> }
>
> // Create object; note there's no constructor, but the property has a
> default so is never uninitialized
> $obj = new Example;
> // On first call to method, the default value is detected and the
> property lazy-loaded
> var_dump($obj->getFoo());
> // Subsequent accesses return the loaded value directly, at the cost of
> a single strict comparison, no magic function needed
> var_dump($obj->getFoo());
I had not thought of this use of Enums, but I love it. It's not as elegant as a tagged enum
for a monad, but it gets you 80% of the way there. Especially if you combine it with match().
enum Result {
case None;
}
function find_user(int $id): User|Result { ... }
$user = match($u = find_user($id)) {
Result::None => some error handling,
default: $u,
};
--Larry Garfield