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

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php

Reply via email to