Hi,
> On 1 Feb 2015, at 02:09, Stanislav Malyshev <[email protected]> wrote:
>
>> Here, there’s no redundant objects made, but if you pass $a on, it’d
>> be automatically copied by PHP, so you don’t need to worry about it
>> being modified.
>
> I don't think it's a particularly good solution in this case, as in many
> cases (especially DI setups, many design patterns, etc.) the whole point
> of creating the object is to pass it around. Just pointlessly copying it
> out of fear somebody somewhere could modify it doesn't sound the best
> way.
Well, that’s the advantage of copy-on-write: you can avoid needless manual copies, and instead
have automatic copying done for you by the language, where needed.
Although implementing copy-on-write for object methods might be a challenge, give PHP doesn’t
track which functions have side effects.
> I'd rather just have a clear separation between mutating and
> non-mutating APIs, and instruct people to use the right ones in right
> situation - i.e. if you created the object or own it, use mutating ones,
> if you got object from outside and do not have full ownership of it, use
> non-mutating ones.
>
This isn’t very nice in practice, though. Mutating APIs are easy to use and performant,
non-mutating APIs are neither of these things. What you want is the benefits of the first without
the disadvantages of the second.
>> Would that make sense? It’s no different than how our existing value
>> types like scalars and arrays work.
>
> Scalars don't have this problem as, except for string offsets (IMHO not
> the best idea to have mutable strings too) scalars can not really be
> changed, just replaced with other scalars. But implementing value
> objects in PHP is not hard right now - if you don't provide any methods
> that allow changing state, you've got an immutable object. It's just not
> always what people using it would want, especially with something as
> complex as HTTP message.
You’re ignoring arrays, which *also* have our copy-on-write behaviour. Also, the bigint RFC (if
passed) would be another kind of mutable scalar. It’s not mutable in very many cases, but it is in
some places as a performance optimisation.
We have value objects, sure, but they’re not efficient. Every mutation requires the creation of a
new object, because you can’t do copy-on-write. Compare that to arrays: mutations there only
create new arrays if the refcount is > 1.
The following code using immutable value objects requires the creation of five new objects:
$a = $somefoo
->withBar(…)
->withBaz(…)
->withQux(…)
->withoutFooBar();
Yet the following code using arrays, which are passed by value in PHP, requires the creation of only
one new array, and modifies in-place:
$a = $somefoo;
$a[‘bar’] = …;
$a[‘baz’] = …;
$a[‘qux’] = …;
unset($a[‘foobar’]);
Is that not superior?
--
Andrea Faulds
http://ajf.me/