On 16 March 2024 00:19:57 GMT, Larry Garfield <la...@garfieldtech.com> wrote:

>Well, reading/writing from within a set/get hook is an obvious use case to 
>support.  We cannot do cached properties easily otherwise:
>
>public string $expensive {
>  get => $this->expensive ??= $this->compute();
>  set { 
>    if (strlen($value) < 50) throw new Exception();
>    $this->expensive = $value;
>  }
>}


To play devil's advocate, in an implementation with only virtual properties, 
this is still perfectly possible, just one declaration longer:

private string $_expensive;
public string $expensive {
  get => $this->_expensive ??= $this->compute();
  set { 
    if (strlen($value) < 50) throw new Exception();
    $this->_expensive = $value;
  }
}

Note that in this version there is an unambiguous way to refer to the raw value 
from anywhere else in the class, if you wanted a clearAll() method for instance.

I can't stress enough that this is where a lot of my thinking comes from: that 
backed properties are really the special case, not the default. Anything you 
can do with a backed property you can do with a virtual one, but the opposite 
will never be true.


The minimum version of backed properties is basically just sugar for that - the 
property is still essentially virtual, but the language declares the backing 
property for you, leading to:

public string $expensive {
  get => $field ??= $this->compute();
  set { 
    if (strlen($value) < 50) throw new Exception();
    $field = $value;
  }
}

I realise now that this isn't actually how the current implementation works, 
but again I wanted to illustrate where I'm coming from: that backed properties 
are just a convenience, not a different type of property with its own rules.



> Being the same also makes the language more predictable, which is also a 
> design goal for this RFC.  (Hence why "this is the same logic as 
> methods/__get/other very similar thing" is mentioned several times in the 
> RFC.  Consistency in expectations is generally a good thing.)

I can only speak for myself, but my expectations were based on:

a) How __get and __set are used in practice. That generally involves reading 
and writing a private property, of either the same or different name from the 
public one; and that private property is visible everywhere equally, no special 
handling based on the call stack.

b) What happens if you accidentally cause infinite recursion in a normal 
function or method, which is that the language eventually hits a stack depth 
limit and throws an error.

So the assertion that the proposal was consistent with expectations surprised 
me. It feels to me like something that will seem surprising to people when they 
first encounter it, but useful once they understand the implications.


Regards,
Rowan Tommins
[IMSoP]

Reply via email to