Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:108704 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 44031 invoked from network); 20 Feb 2020 19:23:22 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 20 Feb 2020 19:23:22 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id DAF56180533 for ; Thu, 20 Feb 2020 09:39:34 -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 wout3-smtp.messagingengine.com (wout3-smtp.messagingengine.com [64.147.123.19]) (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 ; Thu, 20 Feb 2020 09:39:33 -0800 (PST) Received: from compute7.internal (compute7.nyi.internal [10.202.2.47]) by mailout.west.internal (Postfix) with ESMTP id 9E1E95A8 for ; Thu, 20 Feb 2020 12:39:32 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute7.internal (MEProxy); Thu, 20 Feb 2020 12:39:32 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=content-transfer-encoding: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=fMtPw6Yg6TZC5FMOpZVN/Tt0t3NPNdQbZKVRF2bB9 Aw=; b=20OozC6veamY0q9Cv5KBwveS97lqjtz4vEVw4QeVCcAzRwmMXTKbA4emf 9M3rv20kF6eXGHiNvA9sveojSYqCztqZnjjhZN9X+vdsWtprFjw2d6GtAJ3WwL2P c7FtyNE2tC/mFYXtcFumzC9omV0ECNNKcXnwT5+AziICx/A+fcUii3EQvLsZGkuX +ELL3ypWWEGGbrsgRQFsUcEQrOdoXa+kRR93iBlbIXBaA/fLiiZEcIhCGp6/GRlD ogKfn6qMNGtYNSzF9+eVXv1BXwcsIR8ciKRjS803d8z3crTNYePi7d0xNk0RTQDe VJWslkUZ5mcsqjGIeKTKjDQ3MPC4A== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedugedrkedvgddutdehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvffutgfgsehtqhertderreejnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuffhomhgrihhnpehpshgrlhhmrdguvghvnecuvehluhhsthgvrhfuihiivgep tdenucfrrghrrghmpehmrghilhhfrhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtg hhrdgtohhm X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id D5A0A14200A2; Thu, 20 Feb 2020 12:39:31 -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: <8545d15e-ddd5-42be-8405-09697a077234@www.fastmail.com> In-Reply-To: References: Date: Thu, 20 Feb 2020 11:39:05 -0600 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: Re: [PHP-DEV] [RFC] [DISCUSSION] Immutable/final/readonly properties From: larry@garfieldtech.com ("Larry Garfield") On Thu, Feb 20, 2020, at 3:06 AM, Nikita Popov wrote: > On Thu, Feb 20, 2020 at 1:27 AM Matthew Brown > wrote: >=20 > > Someone recently requested something similar for a PHP static analys= is tool > > I wrote (https://psalm.dev/r/f75997a263), though that version only a= llows > > lazy initialisation inside the class in which a given property is de= clared. > > > > Personally I don't like either approach =E2=80=93 I think per-proper= ty getters and > > setters would be a more appropriate venue for this functionality, so= mething > > like: > > > > property int $s { > > public get; > > private set; > > } > > > > This pattern could also be extended to support per-property getter a= nd > > setter methods. > > >=20 > While I certainly like the idea of per-property getters/setters, I thi= nk > that both of these have their place. This RFC proposes readonly proper= ties, > that can be initialized once, and then never modified again, even with= in > the same class. Getters/setters only provide the possibility of having= > asymmetric visibility: They prevent modifying the property from outsid= e the > class, but it can still be modified inside the class. In that, readonl= y > properties offer a stronger guarantee. >=20 > Of course, that does leave the question of how often you need one or t= he > other. Maybe just the asymmetric visibility is sufficient for most > practical purposes, in which case it may not be worthwhile to introduc= e > readonly properties as a separate feature. >=20 > Two comments on the specifics of the RFC: >=20 > The RFC allows specifying a default value for readonly properties. How= ever, > a property for which a default value has been specified will always ha= ve > that value, as it cannot be overwritten in the constructor. If you wri= te > "public readonly int $foo =3D 42", then $object->foo is *always* going= to be > 42. I'm not sure what that would ever be useful for, and it seems like= > something that is bound to be confusing. Maybe it would make more sens= e to > forbid readonly properties with default values? (That way, the rule th= at > readonly properties have to be typed falls out naturally as well -- un= typed > properties always have a default.) >=20 > Regarding the keyword choice, I think you can drop "sealed" from the l= ist, > as it is an established term that affects inheritance, not mutability.= Of > the choices you present, "immutable", "readonly" and "writeonce" seem = like > the most viable candidates. "writeonce", while the one that is most > technically accurate, is also *unnecessarily* technically accurate and= not > intuitive. From the perspective of an API consumer, I think that "read= only" > is the most accurate description of how they are supposed to interact = with > the property. The API contract you want to expose is that they can onl= y > read from the property, not write to it. Calling it "writeonce" would = be > quite confusing in that context, because the API consumer is never exp= ected > to write to the property. In the majority of cases you will be providi= ng > fully initialized objects, in which case they are indeed readonly for = the > consumer -- the details of the write-once property are only relevant i= n > special cases like ReflectionClass::newObjectWithoutConstructor() for > serialization libraries, or lazy initialization like in Marco's > ProxyManager. >=20 > Regards, > Nikita > From M=C3=A1t=C3=A9 Kocsis wrote: > No, it doesn't work, and it seems to be an unrelated feature for me. A= s far > as I understand your > example, it's the topic of the "Constant expressions" RFC. >=20 > I believe the behaviour proposed by my RFC would be still useful in ma= ny > cases where one wants > to be sure that no unexpected modifications can happen with a property= . My > use-cases > would mainly include objects storing different kind of data: events, v= alue > objects, data transfer objects. Yeah, I'm definitely thinking in relation to the earlier discussion, sin= ce I think they're all inter-related. (This, property accessors, and co= nstant expressions.) As Nikita notes above, a read-only property with a default value is... b= asically a constant already. So that's not really useful. For defined-later readonly properties, I'm not sure how the earlier poin= t about reading an unintialized property isn't valid. Currently: class Foo { public string $bar; } $f =3D new Foo(); print $f->bar; // this throws a TypeError. I would expect the exact same behavior if $bar were marked readonly/lock= ed/whatever. Are you saying that's not the case? I do think it's fair to bring in the property accessor discussion here, = as property accessors would allow for the same net functionality as this= property as a special case, albeit with likely more syntax. AFAIR the = issue with them before wasn't that people opposed the idea, just the per= formance impact. If we could address the performance impact, that would give us much more= functionality-for-the-buck, including an equivalent of read-only proper= ties including potentially lazy initialization. Or derive-on-demand beh= avior would also be a big increase in functionality. It's not that I don't see a value to this RFC; I actually have a few pla= ces in my own code where I could use it. It's that I see it as being of= fairly narrow use, so I'm trying to figure out how to increase it so th= at the net-win is worth it. --Larry Garfield