On 02/04/2024 01:17, Ilija Tovilo wrote:
I'd like to introduce an idea I've played around with for a couple of
weeks: Data classes, sometimes called structs in other languages (e.g.
Swift and C#).


Hi Ilija,

I'm really interested to see how this develops. A couple of thoughts that immediately occurred to me...


I'm not sure if you've considered it already, but mutating methods should probably be constrained to be void (or maybe "mutating" could occupy the return type slot). Otherwise, someone is bound to write this:

$start = new Location('Here');
$end = $start->move!('There');

Expecting it to mean this:

$start = new Location('Here');
$end = $start;
$end->move!('There');

When it would actually mean this:

$start = new Location('Here');
$start->move!('There');
$end = $start;


I seem to remember when this was discussed before, the argument being made that separating value objects completely means you have to spend time deciding how they interact with every feature of the language.

Does the copy-on-write optimisation actually require the entire class to be special, or could it be triggered by a mutating method on any object? To allow direct modification of properties as well, we could move the call-site marker slightly to a ->! operator:

$foo->!mutate();
$foo->!bar = 42;

The first would be the same as your current version: it would perform a CoW reference separation / clone, then call the method, which would require a "mutating" marker. The second would essentially be an optimised version of $foo = clone $foo with [ 'bar' => 42 ]

During the method call or write operation, readonly properties would allow an additional write, as is the case in __clone and the "clone with" proposal. So a "pure" data object would simply be declared with the existing "readonly class" syntax.

The main drawback I can see (outside of the implementation, which I can't comment on) is that we couldn't overload the === operator to use value semantics. In exchange, a lot of decisions would simply be made for us: they would just be objects, with all the same behaviour around inheritance, serialization, and so on.


Regards,

--
Rowan Tommins
[IMSoP]

Reply via email to