Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:95741 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 29703 invoked from network); 7 Sep 2016 12:05:12 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 7 Sep 2016 12:05:12 -0000 Authentication-Results: pb1.pair.com header.from=marijic.silvio@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=marijic.silvio@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.214.46 as permitted sender) X-PHP-List-Original-Sender: marijic.silvio@gmail.com X-Host-Fingerprint: 209.85.214.46 mail-it0-f46.google.com Received: from [209.85.214.46] ([209.85.214.46:36219] helo=mail-it0-f46.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id FE/EF-18051-77200D75 for ; Wed, 07 Sep 2016 08:05:11 -0400 Received: by mail-it0-f46.google.com with SMTP id i184so192577962itf.1 for ; Wed, 07 Sep 2016 05:05:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=3gIaqO9slMXtV/Rgifu/aMbMXywM5CjzOriu6PE5zhc=; b=DzeoPWQbBVPpxrQlt2XxmpFTTXpH20j1603lxV1q+PXpq+1+lYvBJwPEtBTp3y2jwg bsBQWVSHvxpLG7XaY8MKUkfRejrlHhDCDiriWnv8JoUZ1sVNV25zfCAORvvRzY1i+hWj vk2Z2bVuw6Jv36dJWQcOustMOl2VrYvkLQx71H63+UbC6BKAfMQtHS4zL1zJgserhen1 qivs5E2YtRxVsXcCGZJpzvLIkZtQs9Bolo6c1J+hXlWSecyOhthJcogjF8TAgyc5taNx nzp9vdKukIMdnF8PrZ85xvMu67d532IYFRzg/owDUg+SsS0q/SWrFtQo+JyaTy+kquZh VcOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=3gIaqO9slMXtV/Rgifu/aMbMXywM5CjzOriu6PE5zhc=; b=cwOz0zA+zpjvZDxhQ6cjODlthokeTAoifmoiZ2EhKnqwEZplOYruptm4GL+UxYo2Xp B5ceEwCKeycYPaeDNm2a8olkvZrjVyk5oq3lia9jQJDnJ4P9ZjVsx+JwnLIFb689iC8j NU0X1gtHKjHzEXLFkx+r18b/tAeGmuYGAyG8zReRajwpjnYhm3hf5MSWEFub6TtJAmvE FIJS5fL/vAc0hRfSf3VVcbTZrnf7R60q9FlcDjorVxVp3W/gNeZ648Izq//XKbbCS9I1 g0DN+rmpTnU1VZowprfFzaKG1Lb7B1xyZulB9jTGvZjoEtfK5T9/H+tY6ZbeJO+JITEG qVZQ== X-Gm-Message-State: AE9vXwMv3rjspcFuNBoIIUrbbOoiPSbyj2WWWeEambapyEHu5BAbIZrhSTeVGq48QA6qJD8h0X33C9RYymiK/g== X-Received: by 10.36.211.16 with SMTP id n16mr5540689itg.6.1473249908704; Wed, 07 Sep 2016 05:05:08 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.237.74 with HTTP; Wed, 7 Sep 2016 05:05:07 -0700 (PDT) In-Reply-To: References: <0e71d28e-1d64-5372-b58d-e54c7afae3b8@fleshgrinder.com> <642a6e78-90ea-cbf0-ec1c-376c24e568c5@fleshgrinder.com> <0800a5ca-3d14-c541-1a1a-2574ec802b8c@fleshgrinder.com> <83fa661e-2d3d-6548-a506-fb969be31c0e@garfieldtech.com> <69D0D60B-3D42-4228-8156-F9E6AFEDF72B@koalephant.com> <388c9bf3-d7bc-7e73-bf44-b4c446c2398b@rochette.cc> Date: Wed, 7 Sep 2016 14:05:07 +0200 Message-ID: To: =?UTF-8?Q?Micha=C5=82_Brzuchalski?= Cc: Stephen Reay , Mathieu Rochette , PHP Internals List Content-Type: multipart/alternative; boundary=001a1145f732794a5e053be9b905 Subject: Re: [PHP-DEV] RFC - Immutable classes From: marijic.silvio@gmail.com (=?UTF-8?Q?Silvio_Mariji=C4=87?=) --001a1145f732794a5e053be9b905 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable 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=C5=82 Brzuchalski = : > 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 kno= w > what references to original object. > There can be cloning objects as they are now - I don't see it usefull, bu= t > 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=C4=87 = : > >> @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" wrote= : >> >> > Hey Matheiu, Silvio, >> > >> > That is my main concern with the inability to clone from outside the >> > class. I don=E2=80=99t think immutable should cause an error in this s= ituation >> - if >> > you really don=E2=80=99t want to allow users to create objects they ca= n=E2=80=99t modify >> > (which I understand) could clone on an immutable object from outside t= he >> > 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=E2=80=99d be happ= y 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 >> wrote: >> > > >> > > >> > > >> > > On 07/09/2016 11:28, Silvio Mariji=C4=87 wrote: >> > >> Hi Stephen, >> > >> >> > >> Cloning is disabled at the moment in implementation because you wou= ld >> > end >> > >> up with a object that you can not change, so you have no use of tha= t. >> > 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 a= n >> > error ? >> > > it means that you might have to use reflection to check if the objec= t >> 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 : >> > >> >> > >>> (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 =E2=80=9Cmagic" as pos= sible. >> > >>> >> > >>> >> > >>> 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 tha= t, >> > what >> > >>> is the point of having this behaviour? >> > >>> Existing built-in immutable classes (like DateTimeImmutable) do no= t >> > >>> prevent cloning, so why should this? >> > >>> >> > >>> - regular cloning from within class method(s) is the suggested way >> to >> > >>> provide =E2=80=9Ccreate a copy of the object with a new value=E2= =80=9D >> functionality. >> > >>> >> > >>> This example was given before, effectively: >> > >>> >> > >>> public function withValue($val) { >> > >>> $clone =3D clone $this; >> > >>> $clone->val =3D $val; >> > >>> >> > >>> return $clone; >> > >>> } >> > >>> >> > >>> >> > >>> >> > >>> >> > >>> >> > >>>> On 7 Sep 2016, at 13:57, Micha=C5=82 Brzuchalski < >> michal@brzuchalski.com> >> > >>> wrote: >> > >>>> 06.09.2016 9:13 PM "Fleshgrinder" >> napisa=C5=82(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 =3D clone $this; >> > >>>>> $clone->value =3D $value; >> > >>>>> return $clone; >> > >>>>> } >> > >>>>> } >> > >>>>> >> > >>>>> $red =3D new Immutable('red'); >> > >>>>> $still_red =3D $red->withValue('red'); >> > >>>>> >> > >>>>> var_dump($red =3D=3D=3D $still_red); // bool(false) >> > >>>>> >> > >>>>> This is a problem in terms of value objects and PHP still does n= ot >> > allow >> > >>>>> us operator overloading. A circumstance that I definitely want t= o >> > >>>>> 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 fron= t >> 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 an= y >> 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 norma= l >> > >>>>> objects and the engine takes care of everything. >> > >>>>> >> > >>>>> This approach also has the advantage that the return value of an= y >> > 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 binar= y >> > >>>>> representation is always the same: >> > >>>>> >> > >>>>> var_dump('string' =3D=3D=3D 'string'); // bool(true) >> > >>>>> >> > >>>>> This is the exact behavior one wants for value objects too. Henc= e, >> > >>>>> immutable objects should have this behavior since they identify >> > >>>>> themselves by their values and not through instances. If I creat= e >> 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 ha= s >> 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 >> > >>>>> > > >>>>> >> > >>>>> final immutable class ValueObject { >> > >>>>> >> > >>>>> public $value; >> > >>>>> >> > >>>>> public function __construct($value) { >> > >>>>> $this->value =3D $value; >> > >>>>> } >> > >>>>> >> > >>>>> public function withValue($value) { >> > >>>>> $this->value =3D $value; >> > >>>>> } >> > >>>>> >> > >>>>> } >> > >>>>> >> > >>>>> class A { >> > >>>>> >> > >>>>> public $vo; >> > >>>>> >> > >>>>> public function __construct(ValueObject $vo) { >> > >>>>> $this->vo =3D $vo; >> > >>>>> } >> > >>>>> >> > >>>>> } >> > >>>>> >> > >>>>> class B { >> > >>>>> >> > >>>>> public $vo; >> > >>>>> >> > >>>>> public function __construct(ValueObject $vo) { >> > >>>>> $this->vo =3D $vo; >> > >>>>> } >> > >>>>> >> > >>>>> } >> > >>>>> >> > >>>>> $vo =3D new ValueObject(1); >> > >>>>> >> > >>>>> $a =3D new A($vo); >> > >>>>> $b =3D new B($vo); >> > >>>>> >> > >>>>> var_dump($a->vo =3D=3D=3D $b->vo); // bool(true) >> > >>>>> >> > >>>>> $a->vo->withValue(2); >> > >>>>> >> > >>>>> var_dump($a->vo =3D=3D=3D $b->vo); // bool(false) >> > >>>>> >> > >>>>> $a->vo->withValue(1); >> > >>>>> >> > >>>>> var_dump($a->vo =3D=3D=3D $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=C5=82 Brzuchalski > brzuchalski.com > --=20 Silvio Mariji=C4=87 Software Engineer 2e Systems --001a1145f732794a5e053be9b905--