Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:120546 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 84352 invoked from network); 8 Jun 2023 19:27:03 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 8 Jun 2023 19:27:03 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 4FA1B180562 for ; Thu, 8 Jun 2023 12:27:01 -0700 (PDT) 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.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_HELO_PASS,SPF_NONE, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS19151 66.111.4.0/24 X-Spam-Virus: No X-Envelope-From: Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Thu, 8 Jun 2023 12:27:00 -0700 (PDT) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 60E315C0127 for ; Thu, 8 Jun 2023 15:26:59 -0400 (EDT) Received: from imap50 ([10.202.2.100]) by compute4.internal (MEProxy); Thu, 08 Jun 2023 15:26:59 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= garfieldtech.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:sender:subject :subject:to:to; s=fm1; t=1686252419; x=1686338819; bh=R10AO0ew1X 7/i/0MmVm0W32NyXTziIKOcDUJgrXY+YA=; b=BbYh0QUSsp2Gz+LaZ6wjrF1oqV TZJvkw73lGn0OmFcyxA7T7QSgKWK10kC3xh/6kMp5MZ2xSDQsCinAWQYc2+VJbqg 2Lv2z85L/LbQ9CXhqxWwMnicrcOaE1ppla72hTScIBDlOdM8S4k+cQ3ERYkAWEpg IQW4nrx+wOnzRDhTc3aMSlwr7KnEtQc3oEUg1rOjOlF5qgscKK/nIszR3kEpH2vr GB3O9Pl3auHnCAivR8DwqrqnMtJA0FpNJDmCCCvvDP07lRQ4R69Esawja6raSdmu IokIAwPO3jopQlJfOK4QbgOB8xs1IeL7KISJGN3yPEk3v8gKsFds8taYbLuA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :content-type:date:date:feedback-id:feedback-id:from:from :in-reply-to:in-reply-to:message-id:mime-version:references :reply-to:sender:subject:subject:to:to:x-me-proxy:x-me-proxy :x-me-sender:x-me-sender:x-sasl-enc; s=fm1; t=1686252419; x= 1686338819; bh=R10AO0ew1X7/i/0MmVm0W32NyXTziIKOcDUJgrXY+YA=; b=B IiOqm3G0W0yX4epE9lpMErMZVm518p+HrTLc9XWYNp7MwIu82paIWMA0MSNlQk4v FPugS+Pp4l498kVQ6+NvmUJWtoab5NxkA3ZFT9w74kgFihwc4s1Y6OqaUSEgOIMc hgzMav22ffWZR3R3IlIRAj2ofPw78lZErhFGGUf50hh/U81E5LaeghOcMlb5zpHZ pCBXUTijJtJQVea6K/omHfgYLDPwltR+a7TQtlbq2+mMPu8dVaoVrDPcDSqLTdjI hYqUh/pgDSS+vodtK+UzhadU+K7KY339O6HEYUx6FgfFcx8it66u5SI2Oq1XbVjD T0Imeb4SZEdEUvPKMFRDw== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrgedtiedgudefkecutefuodetggdotefrod ftvfcurfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfgh necuuegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd enucfjughrpefofgggkfgjfhffhffvufgtgfesthhqredtreerjeenucfhrhhomhepfdfn rghrrhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrd gtohhmqeenucggtffrrghtthgvrhhnpeekkeehledugfehheegkeefvedtvedtteffjefh tefgtefhjeduteeiieffvdejgfenucffohhmrghinhepfehvgehlrdhorhhgnecuvehluh hsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgrrhhrhiesghgr rhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Feedback-ID: i8414410d:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 010391700096; Thu, 8 Jun 2023 15:26:58 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-447-ge2460e13b3-fm-20230525.001-ge2460e13 Mime-Version: 1.0 Message-ID: In-Reply-To: References: <799ae864-6e25-4196-a5ce-0d74600a8378@app.fastmail.com> <280bcea8-9483-4191-80d3-81763a988290@app.fastmail.com> <5db38bc4-a6fd-4cb7-b10d-3ad1a590888c@app.fastmail.com> <39511e44-93cb-4fde-b0ec-ce24ee88f4be@app.fastmail.com> Date: Thu, 08 Jun 2023 19:26:36 +0000 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] [RFC] [Discussion] Clone with From: larry@garfieldtech.com ("Larry Garfield") On Thu, Jun 8, 2023, at 6:15 PM, Nicolas Grekas wrote: >> On Tue, May 30, 2023, at 10:04 PM, Alexandru P=C4=83tr=C4=83nescu wro= te: >> > > On Tue, May 30, 2023, 19:39 Larry Garfield >> > wrote: >> > > >> > >> On Mon, May 29, 2023, at 11:22 PM, M=C3=A1t=C3=A9 Kocsis wrote: >> > >> > To be honest, the current behavior seemed like the natural cho= ice >> for >> > >> > me, and I didn't really consider to execute the __clone() meth= od >> after >> > >> the >> > >> > clone assignments. >> > >> > Do you have a use-case in mind when you need to forward-pass >> > information >> > >> to >> > >> > __clone()? >> > >> >> > >> Not a specific one off hand. It's more a conceptual question. = `with` >> > has >> > >> more contextual awareness than __clone(), so it should have "fir= st >> > crack" >> > >> at the operation, so that if necessary it can make changes that >> > __clone() >> > >> can then respond to. The inverse doesn't make sense. >> > >> >> > >> The only reason for `with` to come after would be to allow `with= ` to >> > >> "override" or "undo" something that __clone() did. Generally >> speaking, >> > if >> > >> you have to undo something you just did, you shouldn't have done= it in >> > the >> > >> first place, so that's a less compelling combination. >> > >> >> > >> This one isn't a deal breaker, but we should be sure to think it >> through >> > >> as it's kinda hard to reverse later. >> > >> >> > > >> > > To me so far also it was natural to assume that __clone is first = and >> only >> > > after that the rest of the operations. >> > > But `with` operations, be it properties assignment or even a clos= ure, >> > would >> > > run in the context of the caller of clone and sometimes this migh= t be >> run >> > > not from a method of the cloned class. >> > > >> > > An example: >> > > There is a class that represents persons of a fictive country/pla= net. >> > > Each person has many properties but has also a first name and a l= ast >> name >> > > and there is a rule: the two names must not start with the same l= etter. >> > > Both names cannot be changed as they are defined readonly. >> > > Creation of new persons can be done using new for new random prop= erties >> > or >> > > using clone to preserve existing properties. But in both cases the >> first >> > > name and last name are randomly chosen. >> > > If we want to control the last name value during clone that would= be >> > > possible using the `with` operation but the logic to allocate a f= irst >> > name >> > > will only happen in `__clone()`method. >> > > >> > > To be able to achieve this we must have __clone last, as there we= have >> > the >> > > internal validations, operations and also access to private/prote= cted >> > > members that are not accesible from where clone is being called. >> > > >> > > Regards, >> > > Alex >> > >> > I... could not understand that in the slightest. Can you show it in >> code? >> > >> > >> >> Sorry for that. Here you go: https://3v4l.org/JIBoI/rfc#vgit.master >> If __clone would be first, there is no way to enforce the rule that a >> person cannot have their first name starting with the same letter as = last >> name. >> > > I'm not sure that's what __clone should be used for. > This looks like a perfect use case for property hooks, isn't it? > > On my side, I would find it unexpected that __clone is called after be= cause > that would break cloning expectations: > Imagine you have a __clone that does some deep cloning (a much more ty= pical > scenario for this construct), > Let's say __clone() does $this->foo =3D clone $this->foo; > > Imagine now that you do: clone $obj with (foo: $bar) > I'd expect $obj->foo =3D=3D=3D $bar after this. But if __clone is call= ed after, > that won't be true, and I don't see how that could be "fixed" if we sw= ap > the order. Would you? > > Nicolas Oh, interesting. There's a nice example case. To make it a bit more co= ncrete, and think aloud...=20 class Pet { public function __construct( public readonly string $name =3D 'Fluffy', ) {} } class Address { ... } class Person { public function __construct( public readonly Pet $pet, public readonly Address $address, } public function __clone() { // Legal now thanks to a previous RFC. $this->address =3D clone ($this->address); } } $p =3D new Person(new Pet(), new Address(blah)); // The person gets a new pet. $p2 =3D clone $p with (pet: new Pet('Bonzo')); In this case, the order of operations is irrelevant. // The person moves. $newAddr =3D new Address(whatever); $p3 =3D clone $p2 with (address: $newAddr); In this case, if the `with` happens first, then the new address object i= s cloned needlessly, but that *probably* doesn't hurt anything. But $ne= wAddr !=3D=3D $p3->address. If the `__clone()` happens first, then the existing address object is cl= oned needlessly, but that *probably* doesn't hurt anything. Because the= assignment happens second, $newAddr =3D=3D=3D $p3->address. So I suppose that's a point in favor of __clone() first. Another option could be to run `with` first, but then pass a list of the= keys that were modified (probably not their values, just the keys?) to = __clone(). It can then do conditional cloning based on that if appropri= ate. I... don't know if that's a good idea or not, nor what the BC impl= ications might be. M=C3=A1t=C3=A9, your thoughts? --Larry Garfield