Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108731 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 87698 invoked from network); 23 Feb 2020 18:49:40 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 23 Feb 2020 18:49:40 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 1F6941804A7 for ; Sun, 23 Feb 2020 09:06:37 -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,SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-ASN: AS11403 64.147.123.0/24 X-Spam-Virus: No X-Envelope-From: Received: from wout5-smtp.messagingengine.com (wout5-smtp.messagingengine.com [64.147.123.21]) (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 ; Sun, 23 Feb 2020 09:06:36 -0800 (PST) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.west.internal (Postfix) with ESMTP id 7D8185BE for ; Sun, 23 Feb 2020 12:06:34 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute7.internal (MEProxy); Sun, 23 Feb 2020 12:06:34 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=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=fm2; bh=0q9AqM s/KDhIn3PTxsuz4A8xAXL6+m14FJiJyxMnXts=; b=V7FUZXBtMMG+Eoj+xjI54e rZyQGeO4UdSIt4qbSHHYm5985VN4abUGuBfpGJ/7WifmhPFIJqyc5nKP/VYb5R61 OK87EjL1bVwsmhq+ymfuPDj4AupCiHXWjn+Ic8IytNcrlFQFEK/OyI8w2/tHgbb6 MDVZvHgbLXkYEVwQ4Xt/mPZksS8sizQH5Icklg2gIoYBJvxzyubfP88k1/Xqjs2+ 2RiCAb/ZL7OHZmGaeomWeKoJdc1yCOCOhKAfnKzaJevrP4+Biitwj2w5LFP9tS83 tHvGvaWics1nPIkggLXZd/OlVdUxKdfs4XDnFY7ViLIgRObSL8/MDv+XUO0xmqFw == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedugedrkeekgdeljecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenuc fjughrpefofgggkfgjfhffhffvufgtsehttdertderredtnecuhfhrohhmpedfnfgrrhhr hicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtghomh eqnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomheplhgr rhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id 87A1D14200A2; Sun, 23 Feb 2020 12:06:33 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.1.7-802-g7a41c81-fmstable-20200203v1 Mime-Version: 1.0 Message-ID: <9ebc648c-39d1-45b1-9f3d-9a799c6dec93@www.fastmail.com> In-Reply-To: <452D962A-C588-4F04-B000-479EBEA9B9DB@newclarity.net> References: <8545d15e-ddd5-42be-8405-09697a077234@www.fastmail.com> <4d9688fe-cc57-44af-903e-05f4cbb1bbcc@www.fastmail.com> <452D962A-C588-4F04-B000-479EBEA9B9DB@newclarity.net> Date: Sun, 23 Feb 2020 11:06:13 -0600 To: "php internals" Content-Type: text/plain Subject: Re: [PHP-DEV] [RFC] [DISCUSSION] Immutable/final/readonly properties From: larry@garfieldtech.com ("Larry Garfield") On Sun, Feb 23, 2020, at 2:39 AM, Mike Schinkel wrote: > > On Feb 21, 2020, at 6:17 PM, Larry Garfield wrote: > > I'm totally on board for better value object support, so that's a good motive for me. The question I have is whether this is really a good stepping stone in that direction or if it would lead down a wrong path and lock us into too much TIMTOWTDI (for the Perl fans in the room). So let's think that through down that path. How would write-once properties lead into properly immutable value objects? Or do they give us that themselves? > > > > The biggest challenge for immutable objects, IMO, is evolving them. Eg, $result->withContentType(...) to use the PSR-7 example. Would we expect people to do it with a method like that, or would there be some other mechanism? If the properties are public, would we offer a more syntactic way to modify them directly? > > > > The with*() method style requires cloning the object. What happens to the locked status of a set property if the object is cloned? Are they then settable again, or do they come pre-locked? > > > > Neither of those seem good, now that I think about it. If they come pre-locked, then you really can't clone, change one property, and return the new one (as is the standard practice now in that case). If they don't come pre-locked, then the newly created object can have everything on it changed, once, which creates a loophole. I'm not sure what the right answer is here. > > > > My other concern is a public property (the most likely use case) would have to be set in the constructor. If it's not, then callers cannot rely on it having been set yet if it's set lazily. And if code inside the class tries to set it lazily, it may already have been set by some external code (rightly or wrongly) and cause a failure. > > > > > How do we address that? There's absolutely use cases where setting everything in the constructor ahead of time is what you'd do anyway, but there are plenty where you wouldn't want to, either, which creates a race condition for who sets it first, or tries to access it before it gets set, etc. (This is where my repeated questions about lazy initialization come from.) > > > I have struggled to follow this RFC thread fully, so if I am getting > something out of context, please note that and I apologize in advance. > > However, it would see that rules for `write once` properties to support > lazy loading would be rather simple: > > 1. Write-once properties can only be updated once. > 2. Write-once properties can only be updated within the class where > they are declared. This is the common use case I think many envision, but nothing in the proposal requires that. A public write-once property (as currently written) would be world-readable, and world-writeable, once. Separate visibility for internal and external access is a separate matter. (Also potentially useful, but not part of the write-once proposal at the moment.) > 3. If you want to update a property from outside the class, create a > set_() method to allow it to happen. > 4. If you do not want it to be set externally, do not implement a > set_() method. > 5. If you want it to be implemented externally sometimes but not > others, implement guard classes inside the set_() method. > > I think that addresses all scenarios, no? > > -Mike It does not. 1) Race condition if I assume that a public write-once property is a materialized value, but access it before it gets materialized. 2) Race condition if internal non-constructor code wants to set the value, but some external routine has set it first. 3) Cloning creates an interesting and complicated case of both of the above. Does a cloned object start with its write-once bits reset or no? There's problems both ways. Making a write-once property implicitly write-only-from-inside-the-class would help address point 2, but not points 1 or 3. Adding separate get/set visibility modifiers is another interesting idea, but is separate and should be evaluated on its own merits. It is not at this time part of this proposal. --Larry Garfield