On 27/05/2021 13:07, Pierre wrote:
So, if it's going to be used and abused in those magic APIs we all use
daily without thinking about it (let's say, hydrators or serializers,
dependency injection containers and all that stuff, and you do
maintain some if I recall) and unlock some performance optimizations
in there, I'd say go for it.
I think "abused" is the right word here. The uninitialized state exists
in the first place because we don't have a way to enforce initialization
in constructors, not because we really wanted a new special value that
is "like null, but even more so".
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());
Unlike abusing "uninitialized" as a third state (next to int and null),
this allows any number of states to be recorded, and treated
appropriately. For instance, an auto-increment key might default to
ORMState::NotYetCalculated, and trigger an error rather than a lazy-load.
Regards,
--
Rowan Tommins
[IMSoP]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: https://www.php.net/unsub.php