Re: Analysis of property visibility, immutability, and cloning proposals
| From: | Olle Härstedt | Date: | Wed, 30 Dec 2020 18:45:05 +0000 |
| Subject: | Re: Analysis of property visibility, immutability, and cloning proposals | ||
| References: | 1 2 3 4 5 6 7 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-112676@lists.php.net to get a copy of this message | ||
2020-12-30 18:31 GMT, Larry Garfield <larry@garfieldtech.com>:
> On Wed, Dec 30, 2020, at 12:15 PM, Rowan Tommins wrote:
>> On 30/12/2020 13:49, Olle Härstedt wrote:
>> > Uniqueness is when you only allow _one_ reference to an object (or
>> > bucket of memory).
>> > [...]
>> >
>> > You can compare a builder pattern with immutability vs non-aliasing
>> > (uniqueness):
>> >
>> > ```
>> > // Immutable
>> > $b = new Builder();
>> > $b = $b->withFoo()->withBar()->withBaz();
>> > myfun($b); // $b is immutable, so $b cannot be modified by myfun()
>> > return $b;
>> > ```
>> >
>> > ```
>> > // Uniqueness
>> > $b = new Builder(); // class Builder is annotated as
>> > non-aliasing/unique
>> > $b->addFoo();
>> > $b->addBar();
>> > $b->addBaz();
>> > myfun(clone $b); // HAVE TO CLONE TO NOT THROW EXCEPTION.
>> > return $b;
>> > ```
>>
>>
>> Thanks, I can see how that solves a lot of the same problems, in a very
>> robustly analysable way.
>>
>> However, from a high-level user-friendliness point of view, I think
>> "withX" methods are actually more natural than explicitly cloning
>> mutable objects.
>>
>> Consider the case of defining a range: firstly, with plain integers and
>> familiar operators:
>>
>> $start = 1;
>> $end = $start + 5;
>>
>> This models integers as immutable values, and + as an operator which
>> returns a new instance. If integers were mutable but not aliasable, we
>> would instead write something like this:
>>
>> $start = 1;
>> $end = clone $start;
>> $end += 5; // where += would be an in-place modification, not a
>> short-hand for assignment
>>
>> I think the first more naturally expresses the desired algorithm. It's
>> therefore natural to want the same for a range of dates:
>>
>> $start = MyDate::today();
>> $end = $start->withAddedDays(5);
>>
>> vs
>>
>> $start = MyDate::today();
>> $end = clone $start;
>> $end->addDays(5);
>>
>>
>> To put it a different way, value types naturally form *expressions*,
>> which mutable objects model clumsily. It would be very tedious if we had
>> to avoid accidentally mutating the speed of light:
>>
>> $e = (clone $m) * ((clone $c) ** 2);
>>
>>
>> > The guarantee in both above snippets is that myfun() DOES NOT modify
>> > $b before returning it. BUT with immutability, you have to copy $b
>> > three times, with uniqueness only one.
>
> That's a good summary of why immutability and with-er methods (or some
> equivalent) are more ergonomic.
>
> Another point to remember: Because of PHP's copy-on-write behavior, full on
> immutability doesn't actually waste that much memory. It does use up some,
> but far less than you think. (Again, based on the tests MWOP ran for PSR-7
> a ways back.)
I thought copy-on-write was only for arrays, not objects?
Olle