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