Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112673 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 82328 invoked from network); 30 Dec 2020 18:56:50 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 30 Dec 2020 18:56:50 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id C0B431804D4 for ; Wed, 30 Dec 2020 10:31:35 -0800 (PST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_LOW,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from wout3-smtp.messagingengine.com (wout3-smtp.messagingengine.com [64.147.123.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Wed, 30 Dec 2020 10:31:35 -0800 (PST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.west.internal (Postfix) with ESMTP id 54C5BB1D for ; Wed, 30 Dec 2020 13:31:33 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute4.internal (MEProxy); Wed, 30 Dec 2020 13:31:33 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender :x-sasl-enc; s=fm1; bh=WJhMo7Liur1seiOMDTcEm3ct0QxNijKCInuUg/0iC hk=; b=cCS/V+INYxn/AJG0J3ED/sZtzZSe/UKAHL2zvU37FgyqxFoonc+XMKa5G m/f7Dj6D1FrK11v7id0aSd/p3WwFwfil6OqgY2+7jnRBOyosVw9PchcITTXA/wfr lT849yTPHlfs3zjr9rnDtCdhrEV8WRwP2QTSxdnTPGovDGNq1+vszpJymG9ZkZT+ +lCWpvi0drtJ7xS2UKwfNq8Mv8pBEzqiYl4/n94Lhy7uk2+TPiQLcjzK0ln21DJT mLTJo0l1HXHb+SzmMCXULvPLjXOk2hQIXWEExzHQ2xO/F+FAjQaMUFOrmCH432/u VWaAGTwL8rGl0YY0kjCntQ6WIKMaA== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvddvfedguddufecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefofgggkfgjfhffhffvufgtgfesthhqredtreerjeenucfhrhhomhepfdfn rghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrd gtohhmqeenucggtffrrghtthgvrhhnpeffffffjeffudfggeevvdeitdetvdfgjefffeff jeelfeejteevheeghffhvdfgleenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmh epmhgrihhlfhhrohhmpehlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomh X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id 7664B14200A2; Wed, 30 Dec 2020 13:31:32 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.3.1-61-gb52c239-fm-20201210.001-gb52c2396 Mime-Version: 1.0 Message-ID: <3e683903-66cb-4a1a-9ff8-22887dbb8dce@www.fastmail.com> In-Reply-To: <7f4fe9ca-1c20-6f69-cef0-a9718af742a3@gmail.com> References: <1d0abb04-4987-43a9-85bc-bccc3bd6be9a@www.fastmail.com> <03108284-740a-4a5d-130f-15b2e67e9df9@mabe.berlin> <459d7ff7-e553-dce9-7d43-c3b1e772e572@gmail.com> <7f4fe9ca-1c20-6f69-cef0-a9718af742a3@gmail.com> Date: Wed, 30 Dec 2020 12:31:09 -0600 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: =?UTF-8?Q?Re:_[PHP-DEV]_Analysis_of_property_visibility,_immutability,_a?= =?UTF-8?Q?nd_cloning_proposals?= From: larry@garfieldtech.com ("Larry Garfield") On Wed, Dec 30, 2020, at 12:15 PM, Rowan Tommins wrote: > On 30/12/2020 13:49, Olle H=C3=A4rstedt wrote: > > Uniqueness is when you only allow _one_ reference to an object (or > > bucket of memory). > > [...] > > > > You can compare a builder pattern with immutability vs non-aliasing > > (uniqueness): > > > > ``` > > // Immutable > > $b =3D new Builder(); > > $b =3D $b->withFoo()->withBar()->withBaz(); > > myfun($b); // $b is immutable, so $b cannot be modified by myfun() > > return $b; > > ``` > > > > ``` > > // Uniqueness > > $b =3D new Builder(); // class Builder is annotated as non-aliasing= /unique > > $b->addFoo(); > > $b->addBar(); > > $b->addBaz(); > > myfun(clone $b); // HAVE TO CLONE TO NOT THROW EXCEPTION. > > return $b; > > ``` >=20 >=20 > Thanks, I can see how that solves a lot of the same problems, in a ver= y=20 > robustly analysable way. >=20 > However, from a high-level user-friendliness point of view, I think=20= > "withX" methods are actually more natural than explicitly cloning=20 > mutable objects. >=20 > Consider the case of defining a range: firstly, with plain integers an= d=20 > familiar operators: >=20 > $start =3D 1; > $end =3D $start + 5; >=20 > This models integers as immutable values, and + as an operator which=20= > returns a new instance. If integers were mutable but not aliasable, we= =20 > would instead write something like this: >=20 > $start =3D 1; > $end =3D clone $start; > $end +=3D 5; // where +=3D would be an in-place modification, not a=20= > short-hand for assignment >=20 > I think the first more naturally expresses the desired algorithm. It's= =20 > therefore natural to want the same for a range of dates: >=20 > $start =3D MyDate::today(); > $end =3D $start->withAddedDays(5); >=20 > vs >=20 > $start =3D MyDate::today(); > $end =3D clone $start; > $end->addDays(5); >=20 >=20 > To put it a different way, value types naturally form *expressions*,=20= > which mutable objects model clumsily. It would be very tedious if we h= ad=20 > to avoid accidentally mutating the speed of light: >=20 > $e =3D (clone $m) * ((clone $c) ** 2); >=20 >=20 > > The guarantee in both above snippets is that myfun() DOES NOT modify= > > $b before returning it. BUT with immutability, you have to copy $b > > three times, with uniqueness only one. That's a good summary of why immutability and with-er methods (or some e= quivalent) are more ergonomic. Another point to remember: Because of PHP's copy-on-write behavior, full= on immutability doesn't actually waste that much memory. It does use u= p some, but far less than you think. (Again, based on the tests MWOP ra= n for PSR-7 a ways back.) > I wonder if that difference can be optimised out by the=20 > compiler/OpCache: detect clones that immediately replace their origina= l,=20 > and optimise it to an in-place modification. In other words, compile=20= > $foo =3D clone $foo with { x: 42 } to $foo->x =3D 42, even if the clon= e is=20 > actually in a "withX" method. In concept, maybe? That's well above my pay grade. :-) --Larry Garfield