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

Reply via email to