Hi Rowan

On Fri, Apr 5, 2024 at 12:28 AM Rowan Tommins [IMSoP]
<imsop....@rwec.co.uk> wrote:
>
> On 03/04/2024 00:01, Ilija Tovilo wrote:
>
> Regardless of the implementation, there are a lot of interactions we will 
> want to consider; and we will have to keep considering new ones as we add to 
> the language. For instance, the Property Hooks RFC would probably have needed 
> a section on "Interaction with Data Classes".

That remark was implying that data classes really are just classes
with some additional tweaks. That gives us the ability to handle them
differently when desired. However, they will otherwise behave just
like classes, which makes it not so different from your suggestion.

> On a practical note, a few things I've already thought of to consider:
>
> - Can a data class have readonly properties (or be marked "readonly data 
> class")? If so, how will they behave?

Yes. The CoW semantics become irrelevant, given that nothing may
trigger a separation. However, data classes also include value
equality, and hashing in the future. These may still be useful for
immutable data.

> - Can you explicitly use the "clone" keyword with an instance of a data 
> class? Does it make any difference?

Manual cloning is not useful, but it's also not harmful. So I'm
leaning towards allowing this. This way, data classes may be handled
generically, along with other non-data classes.

> - Tied into that: can you implement __clone(), and when will it be called?

Yes. `__clone` will be called when the object is separated, as you would expect.

> - If you implement __set(), will copy-on-write be triggered before it's 
> called?

Yes. Separation happens as part of the property fetching, rather than
the assignment itself. Hence, for `$foo->bar->baz = 'baz';`, once
`Bar::__set('baz', 'baz')` is called, `$foo` and `$foo->bar` will
already have been separated.

> - Can you implement __destruct()? Will it ever be called?

Yes. As with any other object, this will be called once the last
reference to the object goes away. There's nothing special going on.

It's worth noting that CoW makes `__clone` and `__destruct` somewhat
nondeterministic, or at least non-obvious.

> > Consider this example, which would > work with the current approach: > > 
> > $shapes[0]->position->zero!();
>
> I find this concise example confusing, and I think there's a few things to 
> unpack here...

I think you're putting too much focus on CoW. CoW should really be
considered an implementation detail. It's not _fully_ transparent,
given that it is observable through `__clone` and `__destruct` as
mentioned above. But it is _mostly_ transparent.

Conceptually, the copy happens not when the method is called, but when
the variable is assigned. For your example:

```php
$shape = new Shape(new Position(42,42));
$copy = $shape; // Conceptually, a recursive copy happens here.
$copy->position->zero!(); // $shape is already detached from $copy.
The ! merely indicates that the value is modified.
```

> The array access doesn't need any special marker, because there's no 
> ambiguity.

This is only true if you ignore ArrayAccess. `$foo['bar']` does not
necessarily indicate that `$foo` is an array. If it were a `Vector`,
then we would absolutely need an indication to separate it.

It's true that `$foo->bar` currently indicates that `$foo` is a
reference type. This assumption would break with this RFC, but that's
also kind of the whole point.

> What is going to be CoW cloned, and what is going to be modified in place? I 
> can't actually know without knowing the definition behind both $item and 
> $item->shape. It might even vary depending on input.

For the most part, data classes should consist of other value types,
or immutable reference types (e.g. DateTimeImmutable). This actually
makes the rules quite simple: If you assign a value type, the entire
data structure is copied recursively. The fact that PHP delays this
step for performance is unimportant. The fact that immutable reference
types aren't cloned is also unimportant, given that they don't change.

Ilija

Reply via email to