Ok, I have some time also so we can together try to write some initial
implementation of that.

2016-09-07 14:10 GMT+02:00 Michał Brzuchalski <mic...@brzuchalski.com>:

> Silvio,
>
> I can try with it tommorow, we'll see about that.
>
>
> 2016-09-07 14:05 GMT+02:00 Silvio Marijić <marijic.sil...@gmail.com>:
>
>> Michal, how much work do you estimate it would take us to implement
>> method modificator solution?
>>
>> 2016-09-07 14:01 GMT+02:00 Michał Brzuchalski <mic...@brzuchalski.com>:
>>
>>> Hi,
>>>
>>> Frozing an immutable object after it's creation is most important
>>> feature of Immutable Classes.
>>> Without it you cannot have guarantee it's internal state is consistent
>>> as it was during creation.
>>> Having methods access to write is quite dangerous - think about CLosure
>>> binded to immutable object - there is a way to change internal state of
>>> such object, and you've broken immutability in it.
>>>
>>> Changing object state is reasonable only on clones, because you newer
>>> know what references to original object.
>>> There can be cloning objects as they are now - I don't see it usefull,
>>> but if somebody really want's it, why not.
>>>
>>> IMHO providing method modificator for changing object in context of
>>> newly created clone is the best solution. The keyword for it isn't chosen
>>> yet, we may discuss it or even vote for it. For now we can call it anyway
>>> while keeping in mind it may change during voting.
>>>
>>>
>>>
>>> 2016-09-07 12:43 GMT+02:00 Silvio Marijić <marijic.sil...@gmail.com>:
>>>
>>>> @Stephan
>>>>
>>>> I am against that any kind of method can make modification on original
>>>> object.
>>>>
>>>> Cloning can be allowed but for this use case where you would pass
>>>> properties that are changing, we would have to modify syntax of clone
>>>> On Sep 7, 2016 12:37 PM, "Stephen Reay" <php-li...@koalephant.com>
>>>> wrote:
>>>>
>>>> > 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
>>>> > >>>
>>>> > >>>
>>>> > >>
>>>> > >
>>>> >
>>>> >
>>>>
>>>
>>>
>>>
>>> --
>>> regards / pozdrawiam,
>>> --
>>> Michał Brzuchalski
>>> brzuchalski.com
>>>
>>
>>
>>
>> --
>> Silvio Marijić
>> Software Engineer
>> 2e Systems
>>
>
>
>
> --
> regards / pozdrawiam,
> --
> Michał Brzuchalski
> brzuchalski.com
>



-- 
Silvio Marijić
Software Engineer
2e Systems

Reply via email to