Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:115207 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 9843 invoked from network); 29 Jun 2021 12:48:54 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 29 Jun 2021 12:48:54 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id A6A781804DB for ; Tue, 29 Jun 2021 06:08:53 -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=-1.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,FREEMAIL_REPLY, HTML_MESSAGE,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE, SPF_PASS autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from mail-lj1-f178.google.com (mail-lj1-f178.google.com [209.85.208.178]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Tue, 29 Jun 2021 06:08:53 -0700 (PDT) Received: by mail-lj1-f178.google.com with SMTP id h6so14772343ljl.8 for ; Tue, 29 Jun 2021 06:08:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=ugY4XV5p9F3IFxShWzhbzB1oWgMGdlZXpP1Ne/eM6vk=; b=C87E+x7BhwnlnffuFKsZ5CaAIhNqy4LyRR4aCsFqqD+/TNk6iP9HQDmlIqAe3SUZLS xEVraoZ/MbR3PGYE+9tZNYVSJLUpSttyjHpXhaphQBWjlwJKsCFIH+p2mfct3K5jyQKC E3uuS3WzWs3cj1H+a4T4GLcVcOsWqC/Lh13rI49nh8IG6f57QKsEZQEflgJAqw/6+EF3 OD25XzgJvJ6PxLFdv3AHHD8cOFEhX4Y3z7gOsJT1RLFE6kn5GogFyYVufmlK8w6YYksU nnb0+LAOGPGp6V9MRE25YlIGCLzUKrBg2VL6J2uJPLudltssKwoNxXF9yHPPnrivKJ0S 3Keg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=ugY4XV5p9F3IFxShWzhbzB1oWgMGdlZXpP1Ne/eM6vk=; b=RyW1udYiCtnsAL6YVoCukfNi5CuvcM8W+u2V+93vBz0T+DER8gn9t8GLY7wHrIZmtf X9jjmgeEfJCDE4sP6e4A5nfxcHCsBvIQtDSnKcE2RthM5so541+fM38fkbhcCblWMSk3 9GwZkcb4kR98gY8M5mixwgjREL6ImJkmADyY+LOmH2cvCDZ7+I8+YB6NlqWH7CL/avy+ D42bWBo3D1re4RazEniQP9YwA/x8lbAkVbXp8W2k/MGaxAlBf/oD6wkgmMlYYTgpawoI bYkbvl9Ywv5cJkRU6W8qV8GphBK6pRt0e+sR8UpP4WyAyjrEsGsvMG4nBrv8GfiCjJ1K p50A== X-Gm-Message-State: AOAM532sZohhAEAMewtcAuPYwllaNbu4IuTX4nm3APcBPkRdUkqwbi/z /s8k74jyI+vzw/BZyMMMnjT4nBMyK+gzO+LuNos= X-Google-Smtp-Source: ABdhPJw1gn4vTnf5VnyM98WyIhmtXTMvMzgJ+EGQq9qoeOU/59p6d3mdzIdE5f/zpkaRaYbCKm6JrBmzgzPwCIMbA3Q= X-Received: by 2002:a2e:a279:: with SMTP id k25mr1257890ljm.29.1624972130034; Tue, 29 Jun 2021 06:08:50 -0700 (PDT) MIME-Version: 1.0 References: <24af2d01-4f6c-4389-a35a-dab50c0b5e66@www.fastmail.com> In-Reply-To: Date: Tue, 29 Jun 2021 15:08:33 +0200 Message-ID: To: Nicolas Grekas Cc: Larry Garfield , php internals Content-Type: multipart/alternative; boundary="00000000000094a7c205c5e74ee1" Subject: Re: [PHP-DEV] Re: [RFC] Readonly properties From: nikita.ppv@gmail.com (Nikita Popov) --00000000000094a7c205c5e74ee1 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, Jun 29, 2021 at 9:14 AM Nicolas Grekas wrote: > Le lun. 28 juin 2021 =C3=A0 18:22, Larry Garfield a >>> =C3=A9crit : >>> >>>> On Mon, Jun 28, 2021, at 11:17 AM, Nicolas Grekas wrote: >>>> > > > I'd like to open the discussion on readonly properties: >>>> > > > https://wiki.php.net/rfc/readonly_properties_v2 >>>> > > > >>>> > > > This proposal is similar to the >>>> > > > https://wiki.php.net/rfc/write_once_properties RFC that has been >>>> > > declined >>>> > > > previously. One significant difference is that the new RFC limit= s >>>> the >>>> > > scope >>>> > > > of initializing assignments. I think a key mistake of the >>>> previous RFC >>>> > > was >>>> > > > the confusing "write-once" framing, which is both technically >>>> correct and >>>> > > > quite irrelevant. >>>> > > > >>>> > > > Please see the rationale section ( >>>> > > > https://wiki.php.net/rfc/readonly_properties_v2#rationale) for >>>> how this >>>> > > > proposal relates to other RFCs and alternatives. >>>> > > > >>>> > > >>>> > > I plan to open voting on this RFC soon. I don't think there's >>>> anything >>>> > > technical left to address here, the discussion mostly comes down t= o >>>> a value >>>> > > judgement. I think everyone has made their position regarding that >>>> clear... >>>> > > >>>> > >>>> > Actually, we talked off the list about a way to possibly make this >>>> work >>>> > with __clone(): >>>> > >>>> > We could allow __clone to have one argument, the object being cloned= . >>>> And >>>> > when the signature declares this argument, then all readonly >>>> properties >>>> > would be set as uninitialized on $this. >>>> > >>>> > A typical __clone function would look like this with readonly >>>> properties: >>>> > function __clone(object $original) >>>> > { >>>> > $this->readonlyProp =3D clone $original->readonlyProp; >>>> > } >>>> > >>>> > That would turn my vote into a +1 if that could be made to work! >>>> >>>> That sounds like it would support deep cloning, but not with-er >>>> methods. There's no way to provide a changed value. It also would me= an a >>>> lot of work on larger objects to transfer across all the properties. = I >>>> don't really see what this would add. >>>> >>> >>> Can you elaborate about the lack of support for withers? Having some >>> work to do doesn't look like an issue to me, especially when there is n= o >>> alternative to compare that too. >>> >> >> I sent that too fast, I agree about withers... :) >> I'm looking for a way to +1 that RFC... >> Any other idea? >> > > And I was too fast agreeing that my proposal to pass the original object > as argument was incompatible with withers. > > I also think that not being compatible with deep cloning is a major issue= . > Past trivial cases, the use cases I can think of where I would use readon= ly > require deep cloning. See eg the Symfony Request object where query param= s, > headers, and a few others expose state as public objects. > > Here is some code that just works with them: > class C > { > public readonly string $foo; > public readonly string $bar; > > private $skipWhenCloning; > > public function withFoo($foo) > { > $this->skipWhenCloning =3D 'foo'; > $clone =3D clone $this; > $clone->foo =3D $foo; > } > > public function withBar($bar) > { > $this->skipWhenCloning =3D 'bar'; > $clone =3D clone $this; > $clone->bar =3D $bar; > } > > public function __clone(self $original) > { > foreach ($this as $k =3D> $v) { > if ($k !=3D=3D $this->skipWhenCloning) { > $this->$k =3D $original->$k; > } > } > $this->skipWhenCloning =3D $original->skipWhenCloning =3D null; > } > } > > You might not like the boilerplate, but that just works. > > Can this be considered Nikita? > Well, it's a nifty hack :) I don't think this is the solution we want to encourage though. It requires you pass extra information through a side-channel -- I think I'd rather not use readonly than write that code. Continuing along the same line, one could extend that to "clone with argument" and do something like this: public function __clone(self $original, array $replacements =3D []) { foreach ($original as $k =3D> $v) { $this->$k =3D $replacements[$k] ?? $original->$k; } } and then do "clone $this(['bar' =3D> $bar])". In any case, I don't want to include changes to cloning in this proposal -- the topic is related, but also orthogonal to readonly properties. Unfortunately, it will not be possible to get cloning changes into PHP 8.1 anymore, due to feature freeze. It's okay to vote against this if cloning is a deal breaker. In that case I'll probably either work on cloning before re-proposing this, or pivot to asymmetric visibility -- it's not my first preference, but it may be the more pragmatic choice. Cloning is definitely the weak point of this proposal. Regards, Nikita --00000000000094a7c205c5e74ee1--