Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108743 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 1133 invoked from network); 24 Feb 2020 22:18:23 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 24 Feb 2020 22:18:23 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DDD9A1804D9 for ; Mon, 24 Feb 2020 12:35: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 66.111.4.0/24 X-Spam-Virus: No X-Envelope-From: Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) (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 ; Mon, 24 Feb 2020 12:35:35 -0800 (PST) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.nyi.internal (Postfix) with ESMTP id B3FC1216C5 for ; Mon, 24 Feb 2020 15:35:35 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute7.internal (MEProxy); Mon, 24 Feb 2020 15:35:35 -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=G7OMBV X0F/uX53gBWIXc6/9f1yH2CIzm8hTaTJS62F4=; b=tjstNPhw5bXuSN+IJy5q3l U7M7U4VJZJrqER71Cpd96BMhXzb4KpE7Tas/fFW1Rd9kxfXEHss5344IJqw6jsYN bDl6NBIqucNHuFyFJsYrynFuoJk5h+MpapAfNRWGqoRPVa/l3+CIwMnfm9/BfkcB Nrs6fEvrhkJn3SUaFJ/5OkSlgPaQxgx+3rNdLHFGUEmxGusSw2SMIC1yWe0WSoHi C8Zcaxjqd4APhpGk5KHFH0//tOLHNBeYSw1Ik5WphZdpF8Yq1Gx87psEH6en5nBM Cm55HePc87Vhu9LJ5dF3f+lDllwUsJ67DSgyUQ5o4aXLrMsRApa+DQx7MSFix2QA == X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedugedrledtgddugedtucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvffutgesthdtredtreertdenucfhrhhomhepfdfnrghr rhihucfirghrfhhivghlugdfuceolhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtoh hmqeenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehl rghrrhihsehgrghrfhhivghlughtvggthhdrtghomh X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id 76AF514200A2; Mon, 24 Feb 2020 15:35:35 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.1.7-947-gbed3ff6-fmstable-20200220v2 Mime-Version: 1.0 Message-ID: <6bcbf0a5-92d8-4cfa-a00f-e0e967fc037e@www.fastmail.com> In-Reply-To: References: <8545d15e-ddd5-42be-8405-09697a077234@www.fastmail.com> <4d9688fe-cc57-44af-903e-05f4cbb1bbcc@www.fastmail.com> Date: Mon, 24 Feb 2020 14:35:15 -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 Mon, Feb 24, 2020, at 7:55 AM, Rowan Tommins wrote: > On Fri, 21 Feb 2020 at 23:18, Larry Garfield wrote: > > > 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. > > > > > As with typed properties, I wonder if there's a way we can introduce a new > initialisation sequence for objects, so that there's a specific point where > the object is considered "fully constructed" after new or clone. > > A couple of brainstormed ideas, with plenty of downsides I'm sure: > > An explicit finalise() function or keyword > > public function withFoo($foo) { > $inst = clone $this; > // all readonly properties are initially "unlocked" > $inst->foo = $foo; > // now lock them, perhaps also checking that no typed properties are > left uninitialised > finalise($inst); // or finalise $inst; > return $inst; > } > > A special code block: > > public function withFoo($foo) { > $inst = clone $this { > // all properties are "unlocked" within this special block > $inst->foo = $foo; > }; > // from here onwards, readonly properties can't be written to > return $inst; > } > > Perhaps could also be used with constructors: > > public function createFromOtherThing(OtherThing $other) { > $inst = new static('some parameter') { > // readonly properties can be written in the constructor, or > within this block > $inst->foo = $other->getFoo(); > }; > // object is "finalised" when the block ends > return $inst; > } If the way to resolve this question is a special "unlocked" mode, I would definitely favor the explicit code block. That way it's self-closing and you can't forget to do so. (Murphy's Law: If you rely on developers remembering to do X to keep code safe, they will promptly forget to do X.) Also, FTR, any approach that forces developers to write a 9 parameter constructor over and over is one I can never get behind, doubly so for something that is currently only a single line. This isn't a case of "pain tells you what not to do"; a value object having a lot of internal properties is a completely valid use case, and "but composition" is not an answer. --Larry Garfield