Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:95703 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 14564 invoked from network); 6 Sep 2016 19:13:21 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 6 Sep 2016 19:13:21 -0000 Authentication-Results: pb1.pair.com header.from=php@fleshgrinder.com; sender-id=unknown Authentication-Results: pb1.pair.com smtp.mail=php@fleshgrinder.com; spf=permerror; sender-id=unknown Received-SPF: error (pb1.pair.com: domain fleshgrinder.com from 77.244.243.84 cause and error) X-PHP-List-Original-Sender: php@fleshgrinder.com X-Host-Fingerprint: 77.244.243.84 mx103.easyname.com Received: from [77.244.243.84] ([77.244.243.84:49389] helo=mx202.easyname.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 08/71-18051-D451FC75 for ; Tue, 06 Sep 2016 15:13:19 -0400 Received: from cable-81-173-132-21.netcologne.de ([81.173.132.21] helo=[192.168.178.20]) by mx.easyname.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1bhLo1-0007tC-0G; Tue, 06 Sep 2016 19:13:13 +0000 Reply-To: internals@lists.php.net 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> To: internals@lists.php.net, michal@brzuchalski.com, larry@garfieldtech.com, =?UTF-8?Q?Silvio_Mariji=c4=87?= Message-ID: Date: Tue, 6 Sep 2016 21:12:58 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="DPb1e7XRKOwBnkSt9s8WN9oeVNaHTQxlb" Subject: Re: [PHP-DEV] RFC - Immutable classes From: php@fleshgrinder.com (Fleshgrinder) --DPb1e7XRKOwBnkSt9s8WN9oeVNaHTQxlb Content-Type: multipart/mixed; boundary="Skk82aH39srdx3VfOOLCD7kL8UESFlFiF"; protected-headers="v1" From: Fleshgrinder Reply-To: internals@lists.php.net To: internals@lists.php.net, michal@brzuchalski.com, larry@garfieldtech.com, =?UTF-8?Q?Silvio_Mariji=c4=87?= Message-ID: Subject: Re: [PHP-DEV] RFC - Immutable classes 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> In-Reply-To: --Skk82aH39srdx3VfOOLCD7kL8UESFlFiF Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable 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 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! 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' =3D=3D=3D '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 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) // :) ?> --=20 Richard "Fleshgrinder" Fussenegger --Skk82aH39srdx3VfOOLCD7kL8UESFlFiF-- --DPb1e7XRKOwBnkSt9s8WN9oeVNaHTQxlb Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXzxVGAAoJEOKkKcqFPVVrn3QP/i6SQ5YMTl5YSz9yBiJHtLmr pOvwiEobfNipnVud5XaGPj7nzHA79wUlVFHeyLbH9ajSUOnKYJayyUQ7tsDrMTQR FsXJTHIpEwCPd2FS7tcGIa7S3DanPAsdBDk414Z+mUNIy2wZ5RUNzBAChjO5Pgtu SsOs4WM4kIYECkWZMKr+ayhZaDp4Mj5g8TvGc6F9IH+uaaQ89041x9MXVzJkxweW azBz4QwTz0x0mUwD9/hOMJEW4ML71pge9EqcTBkb7c4Z/CRDQANAwDF4AihoX/A0 3BYsJQz0ipP8m2Lhrw3HoXRfV6cZA+gV7mZXrZhtILZSOcW2p4qxHobCrW0NpkA/ VhcWmS0QQoCVhdhWglgMczVX18KLGYkgVR5Xn2OzTb+gvExngEN51Mb2rvk7cIW7 rKlE++FJ3iU25UfXm7BhNaKV6/uIlsdxdUPBfl8mOeTWDKkPN4W9lwMbWJQ93ZF+ ZqJXZWif3gEVYWav9CdREQXmZE776SNm9hEsJAYV7im+gOfw/MasZgFi4xBWuUCZ tJibUFg0HbFYstiRyGmZQRXCzyvgvuUbsrFy4XNdw7U2XwSdP6SHktqXuUrVUwQ6 OptWzmMJGuy1woDp6vyifvKoShLA525h7rjHg4On036RREBKJ94OR7a1vCCyA9fX Bpy1TNCYB54DzLGm6A2+ =6ZJS -----END PGP SIGNATURE----- --DPb1e7XRKOwBnkSt9s8WN9oeVNaHTQxlb--