Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127400 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by lists.php.net (Postfix) with ESMTPS id A68181A00BC for ; Mon, 19 May 2025 14:30:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1747664898; bh=EpauMgwjWxFoFejgRHM2x46Vl6haMaoqJoLaLBjMDh0=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=Xcxubt8ZsfJM7qHo50FeA0XreWD15/9giWvHmxqVVY7stPItoGOsXefyMLR4b1BLb wMGlZTJkUJZaOEZlI3sGx+H9s2nExlFX4qrikZbPBT6Ke66/J8vBv1KadMs2gLk3bc wF13Fn20c/pzGzLMxmgZDYv3duDNEfbw91zJwMQDND9RPwN6V+u8FTENQP46fqPQNg qanMXnOD7g+mxEA/WxYL+1TgYyMHKjIJdqIBDOJ/AJ4y5aGj9Mf9bVVsHSKjSQuuSn Hv82sb7GOPLiNmw0TsPG+Mh7EBNxDtzQytdSf74Mha5vSpfW2NmhpWtM2uz6G6stWG /k8/rKDkW/zDQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 69746180057 for ; Mon, 19 May 2025 14:28:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: Error (Cannot connect to unix socket '/var/run/clamav/clamd.ctl': connect: Connection refused) X-Envelope-From: Received: from mail-yb1-f178.google.com (mail-yb1-f178.google.com [209.85.219.178]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Mon, 19 May 2025 14:28:17 +0000 (UTC) Received: by mail-yb1-f178.google.com with SMTP id 3f1490d57ef6-e7569ccf04cso3856324276.0 for ; Mon, 19 May 2025 07:30:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=dqxtech.net; s=google; t=1747665026; x=1748269826; darn=lists.php.net; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=oqVN1pMnqXCM5PNo75V8YjCj8zQHq30kB7umidcgAtg=; b=NYBGRtp5Alg+LX2aFfAhJaQNfI3hWotpLao6lzePLnaMWVA5Jqp0fshhg+7Na/UBqX a9pudgIox4aLiLm4c9hPQ3mUvGdAbgmP2ZHAdRsX7W3ArByAbaOYRtfNVR7yNSWJT8/Q TcAm/qX1mOEnrdJm1Qj8QA7HRVBJ1mXu4/IkjpdoNnHCTv4bpJtgs0KhBwj+roJxbpvR YFgouWbkJQ8H/mKZiRw5nZw7FbntNUcf26kzGnmCq6fmlhfdsxbbyi0ThgLlTDAXslbU llbl7DYVbi76nAprp0sgkqZ/2bSLuSOTihpjLk4u+h1zdLkOpKZaZQByl3dubzoQqc+V gzcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747665026; x=1748269826; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=oqVN1pMnqXCM5PNo75V8YjCj8zQHq30kB7umidcgAtg=; b=K7sIWMDh3GVYznEy6wwaeXUz4WQzbucCAAiHPWkTLJ6lVVU0YkTOMiL6eOL2oVa6EV cAEPdgKLw8InfVnc3X/AZlvb2Ea3lTXdw9TCaVJuHpdh2lfNcB3YQCT9gQCGyDI3iktf hKeh9ZaEwB/VS24Ytlv6sZEtkl/2bjKr9vNmcYbB9cmVn9jBiCtHbpTVCFOIaAXTUgMs MtC+5mn5UbPxg8lYPM2RT9XH+S4GgjrrUxSEcgJr3Dvybh9bbXZ7fkOOg4bA/moOh/1v B1ON6DNCD1wVrdtdL1D6BT23WeBPKwO8prf3MGgVgy+KD2sAp68rMAZ6ZL1TdPKYsR/c bAzg== X-Forwarded-Encrypted: i=1; AJvYcCXYcHAk6UDWprD2GT/iZMWJJOB9Sh/n/0DR0WXWbraO9MadeIwORN86lgtFDvDDYU3WqSRT7B/8wzM=@lists.php.net X-Gm-Message-State: AOJu0YwWHZXHZ1XUrdOf6HpVhkmWkk3/pA6BZi2XlYO7GHcBcZNV0Nod nlcqoOn+kfozoaiFd5b7QaPx85GWZuEBLrjzopaVYJQyuyVDQluRGCRht7gpyxbs/3Q7FDiHVlL F3w6TVktv5CQrAXoo0Go01R9sUxmtuEfJqmwm87SyDA== X-Gm-Gg: ASbGncs9ov0JKFeA8SCokh4oibjI0KxRLdf+9lh4HD4wE/6Irj335xOvBRUsi7z8kXb eFX7iTuMCe0fTWpMgQuU0haeqNHuSq288aqLWkeG4i4q7u6mys1EAsQmypx9jm3LTx6KYKgkfKZ Oa1IA+EWqqyd/AQbGJ/Q803noOGCNFJpjsCB5JZ0xClZWAglJVoVP3pDE2Aeu4JBkxbw== X-Google-Smtp-Source: AGHT+IFm4r+S71XjamoXjUzhXK9EsP6klEyfrKToAp0OdchqNl2OK2Efo/93aQw+Ltnz8J7uQjDY+mMODBnzATmdcX8= X-Received: by 2002:a05:6902:124d:b0:e78:e830:c646 with SMTP id 3f1490d57ef6-e7b6a543c25mr17760386276.49.1747665024576; Mon, 19 May 2025 07:30:24 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net x-ms-reactions: disallow MIME-Version: 1.0 References: In-Reply-To: Date: Mon, 19 May 2025 16:30:13 +0200 X-Gm-Features: AX0GCFu6eZTZMOsMCUYA0GcDlIlM4pbJTLlY-ISL6oicFcwA1RpqvObNXem9v4Y Message-ID: Subject: Re: [PHP-DEV] [RFC] Clone with v2 To: Nicolas Grekas Cc: Larry Garfield , php internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: andreas@dqxtech.net (Andreas Hennings) On Fri, 16 May 2025 at 21:59, Nicolas Grekas wrote: > > > > Le jeu. 15 mai 2025 =C3=A0 16:06, Larry Garfield = a =C3=A9crit : >> >> On Thu, May 15, 2025, at 1:22 AM, Stephen Reay wrote: >> >> > I may be missing something here.. >> > >> > So far the issues are "how do we deal with a parameter for the actual >> > object, vs new properties to apply", "should __clone be called before >> > or after the changes" and "this won't allow regular readonly propertie= s >> > to be modified". >> > >> > Isn't the previous suggestion of passing the new property arguments >> > directly to the __clone method the obvious solution to all three >> > problems? >> > >> > There's no potential for a conflicting property name, the developer ca= n >> > use the new property values in the order they see fit relative to the >> > logic in the __clone call, and it's inherently in scope to write to an= y >> > (unlocked during __clone) readonly properties. >> >> I did some exploratory design a few years ago on this front, looking at = the implications of different possible syntaxes. >> >> https://peakd.com/hive-168588/@crell/object-properties-part-2-examples >> >> What that article calls "initonly" is essentially what became readonly. = The second example is roughly what this RFC would look like if the extra a= rguments were passed to __clone(). As noted in the article, the result is = absolutely awful. >> >> Auto-setting the values while using the clone($object, ...$args) syntax = is the cleanest solution. Given that experimentation, I would not support = an implementation that passes args to __clone and makes the developer figur= e it out. That just makes a mess. >> >> Rob makes a good point elsewhere in thread that running __clone() afterw= ard is a way to allow the object to re-inforce validation if necessary. My= concern is whether the method knows it needs to do the extra validation or= not, since it may be arbitrarily complex. It would also leave no way to r= eject the changes other than throwing an exception, though in fairness the = same is true of set hooks. Which also begs the question of whether a set h= ook would be sufficient that __clone() doesn't need to do extra validation?= At least in the typical case? >> >> One possibility (just brainstorming) would be to update first, then call= __clone(), but give clone a new optional arg that just tells it what prope= rties were modified by the clone call. It can then recheck just those prop= erties or ignore it entirely, as it prefers. If that handles only complex = cases (eg, firstName was updated so the computed fullName needs to be updat= ed) and set hooks handle the single-property ones, that would probably cove= r all bases reasonably well. > > > I like where this is going but here is a variant that'd be even more capa= ble: > > we could pass the original object to __clone. My proposal earlier was to pass the original object _and_ the values that were passed to the clone call, by reference. And this would happen before those values are assigned to the object. class MyClass { public function __construct( public readonly int $x, public readonly int $y, public readonly int $z, ) {} public function __clone(object $original, array &$values): void { // Set a value directly, and modify it. if (isset($values['x'])) { $this->x =3D $values['x'] * 10; // Prevent that the same property is assigned again. unset($values['x']); } } } $obj =3D new C(5, 7, 9); $clone =3D clone($obj, x: 2, y: 3); assert($clone->x =3D=3D=3D 20); // x was update in __clone(). assert($clone->y =3D=3D=3D 3); // y was auto-updated after __clone(). assert($clone->z =3D=3D=3D 9); // z was not touched at all. > > The benefits I see: > - Allow implementing this validation logic you're talking about. > - Allow to skip deep-cloning of already updated properties (that's a sign= ificant drawback of the current proposal - deep cloning before setting is a= potential perf/mem hog built into the engine) : guarding deep-cloning with= a strict comparison would be enough. > - Allow implementing WeakMap that are able to clone weak-properties as ob= jects are cloned. > > On this last aspect, I think it's new to the discussion but it's somethin= g I've always found very limiting when using weak-map: let's say some metad= ata are stored about object $foo in a weakmap, it's currently not possible = to track those metadata across clones without using some nasty tricks. If _= _clone were given the original object, it's be easy to duplicate meta-data = from $foo to $clone. > > I have just one concern significant with adding an argument to __clone: i= t'dbe a BC break to mandate this argument at the declaration level, and add= ing one right now generates an error with current versions of PHP. > However, I think we could (and should if confirmed) provide some FC/BC la= yer by allowing one to use func_get_args() in __clone. The engine could the= n verify at compile time that __clone has either one non-nullable "object" = argument, or zero. This seems reasonable. > > Nicolas > > > >