Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112732 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 95724 invoked from network); 3 Jan 2021 17:20:06 -0000 Received: from unknown (HELO php-smtp4.php.net) (45.112.84.5) by pb1.pair.com with SMTP; 3 Jan 2021 17:20:06 -0000 Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id D02391804D4 for ; Sun, 3 Jan 2021 08:55:50 -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,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL, SPF_HELO_PASS,SPF_NONE autolearn=no autolearn_force=no version=3.4.2 X-Spam-Virus: No X-Envelope-From: Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) (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, 3 Jan 2021 08:55:50 -0800 (PST) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id 8DDB25C00B0 for ; Sun, 3 Jan 2021 11:55:49 -0500 (EST) Received: from imap26 ([10.202.2.76]) by compute4.internal (MEProxy); Sun, 03 Jan 2021 11:55:49 -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=fm1; bh=AkGqbRMLZGcy/Xc6n53akXvqVhQ/dZn2OCmoKbDwI ec=; b=iYRk58kXlcJuS+Q4sHY6RhUotOtyx+UEFYQHg+ZSeQO0JIhwrHvzTpnu/ tozIJ/tCmibnrKTSp74KtIOcYLhNqSjluJ6GjMN80OYumhEDL+1citcm+comzhn4 4N5rGGzIXE7Bas41pkzc7BP3O6VWuT56wUUKRyytp7dMyd8hYOaBXfjZAMCYSAWc hvh76iTU1unV3iWV8LCuQjibGp/M98S3Vv/J70144w5JEPkSvqD9Ny00oRJAK0U0 RMvmZTPUqAL2l7iYIUPwUFADZqMCEiLWQHMjOrUXDlnBVW2CeqtePxVoOGwPeX0p zk+Q5XAishrPf6iZLWbb211R1hVlQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedujedrvdefuddgleehucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvffutgfgsehtqhertderreejnecuhfhrohhmpedfnfgr rhhrhicuifgrrhhfihgvlhgufdcuoehlrghrrhihsehgrghrfhhivghlughtvggthhdrtg homheqnecuggftrfgrthhtvghrnhepffffffejffdugfegvedviedttedvgfejffefffej leefjeetveehgefhhfdvgfelnecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpe hmrghilhhfrhhomheplhgrrhhrhiesghgrrhhfihgvlhguthgvtghhrdgtohhm X-ME-Proxy: Received: by mailuser.nyi.internal (Postfix, from userid 501) id DFD2A14200A2; Sun, 3 Jan 2021 11:55:48 -0500 (EST) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.3.1-61-gb52c239-fm-20201210.001-gb52c2396 Mime-Version: 1.0 Message-ID: <12c6939d-14ed-4f7c-b2bc-189307a20f74@www.fastmail.com> In-Reply-To: References: <1d0abb04-4987-43a9-85bc-bccc3bd6be9a@www.fastmail.com> <03108284-740a-4a5d-130f-15b2e67e9df9@mabe.berlin> <459d7ff7-e553-dce9-7d43-c3b1e772e572@gmail.com> <7f4fe9ca-1c20-6f69-cef0-a9718af742a3@gmail.com> <30906866-1971-8395-05a0-fd78d054bb89@gmail.com> <34d6a045-f7c3-4a77-8b22-378e84b2d1f9@www.fastmail.com> Date: Sun, 03 Jan 2021 10:55:28 -0600 To: "php internals" Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Subject: =?UTF-8?Q?Re:_[PHP-DEV]_Analysis_of_property_visibility,_immutability,_a?= =?UTF-8?Q?nd_cloning_proposals?= From: larry@garfieldtech.com ("Larry Garfield") On Sun, Jan 3, 2021, at 8:28 AM, Olle H=C3=A4rstedt wrote: > >> I like that you connect higher level design patterns with language > >> design. This is the way to go, IMO. Personally, I'd prefer support = for > >> the Psalm notation `@psalm-readonly`, which is the same as your > >> initonly. Clone-with makes sense too, as this construct is already > >> supported in multiple languages. The exact notation doesn't matter > >> that much - my personal choice is OCaml {record with x =3D 10} over= JS > >> spread operator, but OCaml is pretty "wordy" in notation in contras= t > >> to the C tradition that PHP is part of. > >> > >> Reintroducing "objects that pass by value" is a hard pass from me. = The > >> way forward is immutability and constrained mutability (ownership, > >> escape analysis, etc). Psalm also supports array shapes - maybe thi= s > >> can be investigated as an alternative? Since PHP has no tuples. > >> > >> I'm not convinced the added complexity of asymmetric visibility is > >> powerful enough to motivate its existence. Feel free to prove me > >> wrong. :) My choice here would be namespace "internal" (also suppor= ted > >> by Psalm already), but this requires implementation of namespace > >> visibility, a PR that was abandoned. > >> > >> And also, happy new year! > > > > Happy New Year! > > > > I agree that "objects, but passing by value" would not be the right > > solution. I used to think that would be a good part of the solution,= but > > eventually concluded that it would introduce more complexity, not le= ss. > > Eventually, everything people wanted to do with objects they'd want = to do > > with "Records" (for lack of a better term), and if they pass by valu= e but > > are still mutable then you have a weird situation where sometimes ch= anges > > propagate and some don't (depending on if you have a record or objec= t). > > Making it easier to use objects in a value-esque way will get us clo= ser to > > the desired end state. > > > > I think the tldr of my post is this: A single "immutable" flag (what= ever > > it's called) on a class or property would require having lots of hol= es poked > > in it in order to make it useful in practice (mostly what "initonly"= would > > do), but those holes would introduce other holes we don't want (clon= ing an > > object from the outside when you shouldn't). >=20 > I new language feature needs to be both simple and powerful - it's not= > enough to be only powerful. A second problem I see is how asymmetric > visibility would affect the readability of a class, putting extra > strain in understanding it. Thirdly, how does PHP differ from FP > languages like OCaml and Haskell in this regard, neither who uses > visibility in this way? What's acceptable in those languages that > would be unacceptable in PHP? >=20 > Olle I'll disagree slightly. A language feature should introduce more power = than it does complexity. Not everything *can* be made absolutely simple= , but the power it offers is worth it. I'd say it should minimize intro= duced complexity, relative to the power offered. Complexity ideally is = super low, but it's never zero simply by virtue of being "one more thing= " that developers need to know how to read. So in this case, we need to compare the power/complexity of asymmetric v= isibility vs the power/complexity of "immutable... except in these situa= tions." I would argue that asymmetric visibility is more self-documenti= ng, because it states explicitly what those situations are. The other point is that, as noted, "initonly" creates a gap if you have = properties that are inter-dependent. Those then cannot be made public-r= ead, because that would also mean public-clone-with, and thus allow call= ers to violate property relationships. Asymmetric visibility does not h= ave that problem. As far as other language comparisons, I've never written in OCaml and ca= n only barely read Haskell. :-) However, the relevant points as I under= stand them are: * In strictly functional languages (Haskell, etc.), immutability is assu= med by default. So the rest of the syntax, runtime behavior, and commun= ity standards are built on that assumption. That's not true in PHP. * Haskell at least (and I presume other strictly functional languages, a= lthough I've not dug into them in any detail at all) know you're going t= o be calling a bazillion functions, often recursively, and so the engine= can reorder things, execute lazily, skip having a stack entirely, or do= other things to make a deeply recursive function design highly performa= nt. That's not the case in PHP, so usually an iterative algorithm is go= ing to be more performant but requires mutating variables. So the engin= e is optimized for that by default. Compare the idealized functional/immutable fibbonaci with its mutable-it= erative version: function fp_fib(int $n) { return match($n) { 0, 1 =3D> 1, default =3D> fp_fib(n-1) - fp_fib(n-2), }; } function fibonacci_iterative(int $n) { $previous =3D 1; $current =3D 1; $next =3D 1; for ($i =3D 3; $i <=3D $n; ++i) { $next =3D $current + $previous; $previous =3D $current; $current =3D $next; } return $next; } That means you'll often have optimizations where you want to write mutab= le code in the small in order to create effectively-immutable at a highe= r level. We do that now for with-er methods, which mutate the $new obje= ct by necessity before returning it, resulting in an object that seems i= mmutable from the outside. Rust is able to do some of the same kind of thing with zero cost abstrac= tion because its variables are mostly-immutable. * I've read very good arguments that class-level visibility control is a= mistake and always was. Visibility should be at the package level, not= the object level, which is what Go, Rust, and many other newer language= s do. PHP doesn't have packages and it does have class-based visibility= , for better or worse, and neither of those are changing any time soon. = Package-level visibility provides a different level at which to have th= e "immutable on the outside, but internally we can optimize things" barr= ier that is, arguably, better. In PHP, we're stuck with class-level vis= ibility so that's what we've got to work with. That's all background on why I think, in PHP specifically, letting devel= opers emulate immutability at the level they need rather than forcing it= tightly at the language level is going to be a better strategy. (But, of course, I could be convinced otherwise with sufficient demonstr= ated use cases, but they'd have to address the drawbacks of "immutable e= xcept for" I noted previously.) It sounds like no one is against clone-with, though? :-) Anyone want to= argue for clone-arguments? --Larry Garfield