> 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!

Reply via email to