Hey Matheiu, Silvio,

That is my main concern with the inability to clone from outside the class. I 
don’t think immutable should cause an error in this situation - if you really 
don’t want to allow users to create objects they can’t modify (which I 
understand) could clone on an immutable object from outside the class, simply 
return the object itself ?

Re: immutable only externally - yes, as I mentioned I can understand that would 
be a deal-break for some. In that situation, I’d be happy with some way to 
indicate that a method can make changes. Would this then mean that such a 
method could modify the object itself, rather than the clone?

Cheers

Stephen

> On 7 Sep 2016, at 17:09, Mathieu Rochette <math...@rochette.cc> wrote:
> 
> 
> 
> On 07/09/2016 11:28, Silvio Marijić wrote:
>> Hi Stephen,
>> 
>> Cloning is disabled at the moment in implementation because you would end
>> up with a object that you can not change, so you have no use of that. I'll
>> change that as soon as we find some good solution for handling that. Your
>> example is not really clear to me. At what point we should unlock/lock
>> object based on your example?
> what would happen if you tried to clone an immutable object, throw an error ?
> it means that you might have to use reflection to check if the object is 
> immutable before cloning it. otherwise making a class immutable would be a BC
>> 
>> DateTimeImmutable does not prevent cloning because immutability is achieved
>> by encapsulation, and we want to get rid of the need of encapsulation in
>> our implementation of immutable objects.
>> 
>> Best,
>> Silvio.
>> 
>> 2016-09-07 11:05 GMT+02:00 Stephen Reay <php-li...@koalephant.com>:
>> 
>>> (Sorry for any dupes, sent from wrong address originally)
>>> 
>>> From a developer point of view, I would suggest that a feature should aim
>>> to be as clear to understand with as little “magic" as possible.
>>> 
>>> 
>>> If the goal of an immutable class is to allow public properties to be made
>>> read-only, my expectation would be that:
>>> 
>>> - write access to any public property from outside class context, is an
>>> error.
>>> 
>>> This seems to be pretty much accepted by everyone
>>> 
>>> 
>>> - clone still works as expected
>>> 
>>> There has been some suggestion that clone $immutableObj should not be
>>> allowed. Unless there is some specific language/engine gain by that, what
>>> is the point of having this behaviour?
>>> Existing built-in immutable classes (like DateTimeImmutable) do not
>>> prevent cloning, so why should this?
>>> 
>>> - regular cloning from within class method(s) is the suggested way to
>>> provide “create a copy of the object with a new value” functionality.
>>> 
>>> This example was given before, effectively:
>>> 
>>> public function withValue($val) {
>>>         $clone = clone $this;
>>>         $clone->val = $val;
>>> 
>>>         return $clone;
>>> }
>>> 
>>> 
>>> 
>>> 
>>> 
>>>> On 7 Sep 2016, at 13:57, Michał Brzuchalski <mic...@brzuchalski.com>
>>> wrote:
>>>> 06.09.2016 9:13 PM "Fleshgrinder" <p...@fleshgrinder.com> napisał(a):
>>>>> I understand the concerns of all of you very well and it's nice to see a
>>>>> discussion around this topic. Fun fact, we are not the only ones with
>>>>> these issues: https://github.com/dotnet/roslyn/issues/159
>>>>> 
>>>>> On 9/6/2016 6:01 PM, Larry Garfield wrote:
>>>>>> How big of a need is it to allow returning $this instead of $clone,
>>>>>> and/or can that be internalized somehow as well?  With copy-on-write,
>>>>>> is that really an issue beyond a micro-optimization?
>>>>> I asked the same question before because I am also unable to answer this
>>>>> question regarding the engine.
>>>>> 
>>>>> However, for me it is more than micro-optimization, it is about
>>> identity.
>>>>> final class Immutable {
>>>>>   // ... the usual ...
>>>>>   public function withValue($value) {
>>>>>     $clone = clone $this;
>>>>>     $clone->value = $value;
>>>>>     return $clone;
>>>>>   }
>>>>> }
>>>>> 
>>>>> $red = new Immutable('red');
>>>>> $still_red = $red->withValue('red');
>>>>> 
>>>>> var_dump($red === $still_red); // bool(false)
>>>>> 
>>>>> This is a problem in terms of value objects and PHP still does not allow
>>>>> us operator overloading. A circumstance that I definitely want to
>>>>> address in the near future.
>>>>> 
>>>>> But the keyword copy-on-write leads me to yet another proposal, actually
>>>>> your input led me to two new proposals.
>>>>> 
>>>>> # Copy-on-Write (CoW)
>>>>> Why are we even bothering on finding ways on making it hard for
>>>>> developers while the solution to our problem is directly in front of us:
>>>>> PHP Strings!
>>>>> 
>>>> AFAIK CoW in case of objects would be impossible to implement.
>>>> 
>>>>> Every place in a PHP program refers to the same string if that string is
>>>>> the same string. In the second someone mutates that string in any way
>>>>> she gets her own mutated reference to that string.
>>>>> 
>>>>> That's exactly how we could deal with immutable objects. Developers do
>>>>> not need to take care of anything, they just write totally normal
>>>>> objects and the engine takes care of everything.
>>>>> 
>>>>> This approach also has the advantage that the return value of any method
>>>>> is (as always) up to the developers.
>>>>> 
>>>>> (Cloning is disabled and results in an error as is because it makes no
>>>>> sense at all.)
>>>>> 
>>>>> # Identity
>>>>> This directly leads to the second part of my thoughts and I already
>>>>> touched that topic: identity. If we have two strings their binary
>>>>> representation is always the same:
>>>>> 
>>>>> var_dump('string' === 'string'); // bool(true)
>>>>> 
>>>>> This is the exact behavior one wants for value objects too. Hence,
>>>>> immutable objects should have this behavior since they identify
>>>>> themselves by their values and not through instances. If I create two
>>>>> instances of Money with the amount 10 and the Currency EUR then they are
>>>>> always the same, no matter what. This would also mean that no developer
>>>>> ever needs to check if the new value is the same as the existing one,
>>>>> nor does anyone ever has to implement the flyweight pattern for
>>>>> immutable objects.
>>>>> 
>>>>> A last very important attribute is that it does not matter in which
>>>>> thread an immutable value object is created because it always has the
>>>>> same identity regardless of it.
>>>>> 
>>>>> This could easily be achieved by overwriting the object hashes
>>>>> (spl_object_hash) with something that hashes based on the values, and
>>>>> predictably across threads (UUIDs?).
>>>>> 
>>>>> # Full Example
>>>>> <?php
>>>>> 
>>>>> final immutable class ValueObject {
>>>>> 
>>>>> public $value;
>>>>> 
>>>>> public function __construct($value) {
>>>>>   $this->value = $value;
>>>>> }
>>>>> 
>>>>> public function withValue($value) {
>>>>>   $this->value = $value;
>>>>> }
>>>>> 
>>>>> }
>>>>> 
>>>>> class A {
>>>>> 
>>>>> public $vo;
>>>>> 
>>>>> public function __construct(ValueObject $vo) {
>>>>>   $this->vo = $vo;
>>>>> }
>>>>> 
>>>>> }
>>>>> 
>>>>> class B {
>>>>> 
>>>>> public $vo;
>>>>> 
>>>>> public function __construct(ValueObject $vo) {
>>>>>   $this->vo = $vo;
>>>>> }
>>>>> 
>>>>> }
>>>>> 
>>>>> $vo = new ValueObject(1);
>>>>> 
>>>>> $a = new A($vo);
>>>>> $b = new B($vo);
>>>>> 
>>>>> var_dump($a->vo === $b->vo); // bool(true)
>>>>> 
>>>>> $a->vo->withValue(2);
>>>>> 
>>>>> var_dump($a->vo === $b->vo); // bool(false)
>>>>> 
>>>>> $a->vo->withValue(1);
>>>>> 
>>>>> var_dump($a->vo === $b->vo); // bool(true)
>>>>> 
>>>>> // :)
>>>>> 
>>>>> ?>
>>>>> 
>>>>> --
>>>>> Richard "Fleshgrinder" Fussenegger
>>>>> 
>>> 
>>> --
>>> PHP Internals - PHP Runtime Development Mailing List
>>> To unsubscribe, visit: http://www.php.net/unsub.php
>>> 
>>> 
>> 
> 


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to