Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:127391 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 322F61A00BC for ; Fri, 16 May 2025 19:58:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1747425365; bh=+mRBpOv9VsTeYpKSMKSA3EmzECwA0SQ9z0Nqh+5C5vQ=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=LRkPRdJjNsfpzWRHB9XrgPXTEIQKmeuM/5zVDgYL5e0zzNR2dhIM56r01vElm0s7s atwwM2fqMt8ocJoibBdpZK7Z4/YPOCTKkPiLnK6+NpQT/h8MIDz6bLM/yyxi9BZUVX dJXOWn0r4jYmw2iu7NjzWKsqyU5Hsvt33OjRbsiNAVXwfMguObiT9a6I2hX0j2EarL ZOGcXFsTMkb2LVnAPO90UwsHKNM/K4p2nVDYSw9pa9G2lZgXejL9Ry3zJVU5qHd/gL RnfcgSbDtc8PdnOAM6Jbew61h4/DLtszVhyBuCdALhUNV9RpAiU0vt8miO9aZC3OGZ Ltk+rehDMVuJQ== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id AC959180212 for ; Fri, 16 May 2025 19:56:04 +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,FREEMAIL_FROM, HTML_MESSAGE,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-lj1-f174.google.com (mail-lj1-f174.google.com [209.85.208.174]) (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 ; Fri, 16 May 2025 19:56:04 +0000 (UTC) Received: by mail-lj1-f174.google.com with SMTP id 38308e7fff4ca-327ff195303so17290711fa.1 for ; Fri, 16 May 2025 12:58:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1747425493; x=1748030293; darn=lists.php.net; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=4nH2lODa8U3VTiwgCU1z+PnAgrVWjfdiaL+a1MPNunY=; b=X/GS+HsSbQjHArplNM5ILp4LZ4FdO2oaz2KWAw3M8xSgikuuAsZWBxzKM+mU6M+GiN 3ds+AZIwAYNtCvS+x3Xw1VvxSqzrGcM5U/fJ++yxO+4Xm2k+8o/alhmYivWZ8/TyfLlR mVEEME0Fifl9PzbfBGur43zlPrzjbFq8r6VToo3CUJliDK+m9ASkhNrQG6Lz8s/D2hB5 eKvyYOEVmT1bvMnCfifbGKkcomMFqbq+C5wr9UcDnxZ+aEZxjG0jfYvqR4Ge5VEWu23Q R03dxvK6EZ30zBgM3qkDT03Q54lMtVbK8XKkHszq7C7AX6fo1dNv43tSrQYicazcFZYZ ZO5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747425493; x=1748030293; h=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=4nH2lODa8U3VTiwgCU1z+PnAgrVWjfdiaL+a1MPNunY=; b=Mmq6yjHVKanmAnxjC9Lr1dQHPD409l1F4wrx8f7ODLDWozlZmKrrbmsDEr+oU5MVtS EF7s4vD4cY4s6U62ZdoAXGVmfRUJ4ccx0b4eBwHEihhbS53j123IzJ2oqtdCMR1tdihm f3DNv7Wq4+d8vzKnuxOZPsYQ7RJnw1W2X1ODqLLvrB1064An+HwMSOYrHu1OL1R5Kl6E k76kF2ZCcsg4+6TQbjh7w9dR83XQD1yAwhtP6T5O/5BHmU5uNKxpcanqm5W4tWCtqDTw WpvoS+1kHJZznbyM5kXNz2e8x52FvU2J2PK6B5gRb1w7b57YKVRiRfcYjdq9B6ktJXgJ y+qg== X-Gm-Message-State: AOJu0YzrjzXuuX6j0wgdVDxmtXP7P5rlNge2O6aNlc5nIfqLmjP1wT1Z goTH5QW3w3NWamP0hSEEeqiV+/+RQVYU+RhwrVsdQrC06e+DQEieVEtz6Rs2fx9PPbSm6WoMevO Ic4xStNN6gwthftHwwu8FxFkrHtnHfZ7vJZ2WDzg= X-Gm-Gg: ASbGncsdatBTTlgxfSldPDrvn6dqhlKn/VrF7/XO8KTcbLpG/SOiSRZ14oN9kn3JSYU WfDeYuByMdLNuMstiIfSTbLhHq/Z4H/vr13MfcLGDARN+PKgHMroTmznVTQcN3Iy3DXt3oZNJvm 8bE7AIiKmp262XqSPPHxeqx5t6AWJ9hhOR X-Google-Smtp-Source: AGHT+IEU3VDSa0wW91kYCypK0IlXtN+WGWdgIpDUvfpFI7Z+3KIxYptD2+Qo6vBYVw3Kv3WYB/rwmG8r8ESrlRx09b0= X-Received: by 2002:a2e:bc03:0:b0:30b:f775:bae0 with SMTP id 38308e7fff4ca-328077af217mr16521341fa.36.1747425492576; Fri, 16 May 2025 12:58:12 -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: Fri, 16 May 2025 21:58:00 +0200 X-Gm-Features: AX0GCFuJpuHbw5lUxtiUM_aZdeTp5ubVkn1rlXnRTqDYjumcNfQcGBVF_6D353o Message-ID: Subject: Re: [PHP-DEV] [RFC] Clone with v2 To: Larry Garfield Cc: php internals Content-Type: multipart/alternative; boundary="000000000000c1aec80635463335" From: nicolas.grekas+php@gmail.com (Nicolas Grekas) --000000000000c1aec80635463335 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable 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 properties > > 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 can > > 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 any > > (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 > arguments 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 i= s > the cleanest solution. Given that experimentation, I would not support a= n > implementation that passes args to __clone and makes the developer figure > it out. That just makes a mess. > > Rob makes a good point elsewhere in thread that running __clone() > afterward 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 ext= ra > validation or not, since it may be arbitrarily complex. It would also > leave no way to reject the changes other than throwing an exception, thou= gh > in fairness the same is true of set hooks. Which also begs the question = of > whether a set hook 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 > properties were modified by the clone call. It can then recheck just tho= se > properties or ignore it entirely, as it prefers. If that handles only > complex cases (eg, firstName was updated so the computed fullName needs t= o > be updated) and set hooks handle the single-property ones, that would > probably cover all bases reasonably well. I like where this is going but here is a variant that'd be even more capable: we could pass the original object to __clone. 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 significant 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 objects are cloned. On this last aspect, I think it's new to the discussion but it's something I've always found very limiting when using weak-map: let's say some metadata 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: it'dbe a BC break to mandate this argument at the declaration level, and adding one right now generates an error with current versions of PHP. However, I think we could (and should if confirmed) provide some FC/BC layer by allowing one to use func_get_args() in __clone. The engine could then verify at compile time that __clone has either one non-nullable "object" argument, or zero. Nicolas --000000000000c1aec80635463335 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable


Le=C2=A0jeu. 15= mai 2025 =C3=A0=C2=A016:06, Larry Garfield <larry@garfieldtech.com> a =C3=A9crit=C2=A0:
=
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 ac= tual
> object, vs new properties to apply",=C2=A0 "should __clone b= e called before
> or after the changes" and "this won't allow regular read= only properties
> to be modified".
>
> Isn't the previous suggestion of passing the new property argument= s
> directly to the __clone method the obvious solution to all three
> problems?
>
> There's no potential for a conflicting property name, the develope= r can
> 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 t= o any
> (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 rea= donly.=C2=A0 The second example is roughly what this RFC would look like if= the extra arguments were passed to __clone().=C2=A0 As noted in the articl= e, the result is absolutely awful.

Auto-setting the values while using the clone($object, ...$args) syntax is = the cleanest solution.=C2=A0 Given that experimentation, I would not suppor= t an implementation that passes args to __clone and makes the developer fig= ure it out.=C2=A0 That just makes a mess.

Rob makes a good point elsewhere in thread that running __clone() afterward= is a way to allow the object to re-inforce validation if necessary.=C2=A0 = My concern is whether the method knows it needs to do the extra validation = or not, since it may be arbitrarily complex.=C2=A0 It would also leave no w= ay to reject the changes other than throwing an exception, though in fairne= ss the same is true of set hooks.=C2=A0 Which also begs the question of whe= ther a set hook would be sufficient that __clone() doesn't need to do e= xtra validation?=C2=A0 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 properti= es were modified by the clone call.=C2=A0 It can then recheck just those pr= operties or ignore it entirely, as it prefers.=C2=A0 If that handles only c= omplex cases (eg, firstName was updated so the computed fullName needs to b= e updated) and set hooks handle the single-property ones, that would probab= ly cover all bases reasonably well.

I like = where this is going but here is a variant that'd be even more capable:<= /div>

we could pass the original object to __clone.

The benefits I see:
- Allow implementing thi= s validation logic you're talking about.
- Allow to skip deep= -cloning of already updated properties (that's a significant drawback o= f the current proposal - deep cloning before setting is a potential perf/me= m hog built into the engine) : guarding deep-cloning with a strict comparis= on would be enough.
- Allow implementing WeakMap that are able to= clone weak-properties as objects are cloned.

On t= his last aspect, I think it's new to the discussion but it's someth= ing I've always found very limiting when using weak-map: let's say = some metadata are stored about object $foo in a weakmap, it's currently= not possible to track those metadata across clones without using some nast= y tricks. If __clone were given the original object, it's be easy to du= plicate meta-data from $foo to $clone.

I have just= one concern significant with adding an argument to __clone: it'dbe a B= C break to mandate this argument at the declaration level, and adding one r= ight now generates an error with current versions of PHP.
However= , I think we could (and should if confirmed) provide some FC/BC layer by al= lowing one to use func_get_args() in __clone. The engine could then verify = at compile time that __clone has either one non-nullable "object"= argument, or zero.

Nicolas



=C2=A0
--000000000000c1aec80635463335--