> On 11. Jul 2025, at 13:02, Rob Landers <rob@bottled.codes> wrote: >> >> Please remember that the RFC will allow `readonly` on backed properties >> only, not on virtual hooked properties. >> Nothing from your example would work, and it would result in: >> Fatal error: Hooked virtual properties cannot be declared readonly >> My proposed alternative implementation with caching addresses the concern >> Claude and Tim had and will make this hold: >> >> ```php >> class Unusual >> { >> public function __construct( >> public readonly int $value { >> get => $this->value * random_int(1, 100); >> } >> ) {} >> } >> >> $unusual = new Unusual(1); >> var_dump($unusual->value === $unusual->value); // true >> ``` >> >> – Nick > > Hey Nick, > > I was merely illustrating the different types, you can simply replace them > with non-virtual examples. To your idea of forced memoization, I'm not sure > that's a good idea. In cases where its a single execution context per > request, it may be fine, but in cases of worker mode on frankenphp, where > readonly objects may live for quite awhile, it may not be. Generally, > memoization is an optimization, not a property of a value. > > In your example above, this breaks the principle of least astonishment, and > potentially violates referential transparency due to the calculation being > non-pure. Referential transparency basically says we can can replace the use > of the variable with it's value (in this case, $ususual->value with > $unusual->backing_value * random_int(1, 100)). If it is memoized, we cannot. > There isn't a way to express that it is one value the first time (random) and > a different value the next time (the previous computation). This is a bit > dangerous because the programmer has no way to reliably reason about the code > as if the expression can be substituted freely. > > — Rob
Hey Rob, 1) Well, we cannot have it both in the same time. Either we want a strict guarantee that the value doesn’t change after the first `get` hook call on a `readonly` property, or we want the opposite. So the proposed solution now is to be strict by default. If you want it non-cached you can use non `readonly`. 2) The same point could be made outside of "readonly hooks", for everything with any kind of randomness or external state (database, filesystem, …) source. That’s the trade-off. I find it very acceptable as a solution for the concern brought up by Claude and Tim. Cheers, Nick Aside: I just learned about your “records” RFC. Good stuff!