Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:122662 X-Original-To: internals@lists.php.net Delivered-To: internals@lists.php.net Received: from php-smtp4.php.net (php-smtp4.php.net [45.112.84.5]) by qa.php.net (Postfix) with ESMTPS id 64DF71AD8F6 for ; Sun, 17 Mar 2024 00:01:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=php.net; s=mail; t=1710633713; bh=O0cw4styhZnawx0siSyf50MxyBRH+BlfBVfFnfaBEYk=; h=References:In-Reply-To:From:Date:Subject:To:From; b=YbkiSTQtuy80vKBRflOD40t/EGHDxImUllr2g9v+gpflQWIoNAAWkPCEQ5OTKODSf fDtZXOLU+nh/MpYCDw5M9ldI0UiEl1rT61RaDlu4AgPBN6RCEswLVkH+Sb4uejkVE0 zPGG0jk2zat+ETPKIVcdfVwN0W+K6EOWqWSovG8/yJfhORxU0NtbdmUPj9WAPTrNPN g/5w2ANJhyyzIEYFHSx8TLKf2Ue2EA3xrXFNjMjPvndfXnZXjVzxGTVDPxGrRPjTwq j2IAh0cXOmPVNx90YmrMVR0cmrNzJRgSbuR+cbgRgtdhogZ2gri8uGo6EdR7fBl7uj ez5wZlkDIc9aA== Received: from php-smtp4.php.net (localhost [127.0.0.1]) by php-smtp4.php.net (Postfix) with ESMTP id 05C84180081 for ; Sun, 17 Mar 2024 00:01:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.0 (2022-12-13) on php-smtp4.php.net X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=BAYES_50,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,DMARC_PASS,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS, T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=4.0.0 X-Spam-Virus: No X-Envelope-From: Received: from mail-oi1-f172.google.com (mail-oi1-f172.google.com [209.85.167.172]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by php-smtp4.php.net (Postfix) with ESMTPS for ; Sun, 17 Mar 2024 00:01:52 +0000 (UTC) Received: by mail-oi1-f172.google.com with SMTP id 5614622812f47-3c37af44dcbso885975b6e.3 for ; Sat, 16 Mar 2024 17:01:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1710633693; x=1711238493; darn=lists.php.net; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=745OUf3vN06ZhGi9BpJ2+g0JPyb9+5+UqalW0MuVLaA=; b=B0If74RSV58MbJjDhLZjCyBqjILwUGEFBHft3tz4DxWUsiBJ37aDaD8QjELgcH01Um oN6uW3J9+HpQn2Sbm8ReaMiSypZjxHyrmuZaTZVUyXSA6EsG6jwAo1NDm2pxXpxUd0mk Jgv/UnxadSuStIjV125JQo6TE7NNkGnmsyqMomoU9dKJb3ovJ8lsUTmnsWHhWFMMWkMo OJM6lmOYjLaF7sw+qfR2UDwTL2DM5ca+p5bgFXABlfwTRIKuFcAi7EhaNdOvYIhvOkbP FCdJNvFsRwlqI2HE/LWHIFuhXHF3YwgoRC9cMfuo9wjfHJY6AQc208wda1+BNxYXEDG8 0fwg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1710633693; x=1711238493; h=content-transfer-encoding:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=745OUf3vN06ZhGi9BpJ2+g0JPyb9+5+UqalW0MuVLaA=; b=MKlS7kxHXcHG+fAE1usVmQcnw4HR4WRTjaV+/UxJkiTFmHr3Qphzn49emWPwJm8uYy eo8zQTha/0eXBiEj6ppIrzGecNjjClMhvvkvAgUJOXXKZ7hTj2ntHR3ffuDTsIU+xi2K WTv40KJA879igBNWtHIK+DJPwFsyHHHMMciwXf54xZV1oj4IepHGEaYoDUnzztR/Kmdj ekRr7YnVaq1BGvMncWOOpAZlZ36qII0zuwCg5ODo1F7Mc5BrnAoFeUZ1NvS8hIeP9Xhe GkNd+JypEW2Y73kRffez4g5jI59XW4cxeWyohsqt4nmTWb/GLyFXywTHZtuT+Gqp4OY+ vv5A== X-Gm-Message-State: AOJu0YyXfR+KC11GnNPyDJDPBIZQ930aULyKwMda3Dh99KDXvAtl4G36 q+1buPyimejGH0FCUmHD+zW80P2XYTMJGllSog0CgCY4fRbtXaG2FU25gACSsbVnqw4nNrAo6gs oSnOBXKN8mqjbw5scPdoU4/EFy/GHWiNp4DyIeeOi X-Google-Smtp-Source: AGHT+IHO/dggei0UvSGpAeuuuCjmQEQWU9xj6Gq7Hy9I04XxL4BI2IUPbggg07a62SuCypu7+CipOA6eun/KIQzjVRM= X-Received: by 2002:a05:6808:2e96:b0:3c2:2f29:7d72 with SMTP id gt22-20020a0568082e9600b003c22f297d72mr10788415oib.2.1710633692799; Sat, 16 Mar 2024 17:01:32 -0700 (PDT) Precedence: bulk list-help: list-post: List-Id: internals.lists.php.net MIME-Version: 1.0 References: <7eada0fd-39c5-4a89-8c74-80c671801a2d@app.fastmail.com> <1698692e-8eb1-4bfc-a743-375696cd8f1c@rwec.co.uk> <154481e0-5f62-4026-994a-28a644d71527@app.fastmail.com> <46609F15-DD40-4BD2-A78A-16021C3447C8@rwec.co.uk> In-Reply-To: Date: Sun, 17 Mar 2024 01:01:21 +0100 Message-ID: Subject: Re: [PHP-DEV] [RFC[ Property accessor hooks, take 2 To: PHP internals Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable From: tovilo.ilija@gmail.com (Ilija Tovilo) Hi Rowan On Sat, Mar 16, 2024 at 8:23=E2=80=AFPM Rowan Tommins [IMSoP] wrote: > > I still think there will be a lot of users coming from other languages, o= r from using __get and __set, who will look at virtual properties first. Ma= king things less surprising for those people seems worth some effort, but I= 'm not asking for a complete redesign. For clarity, you are asking for a way to make the "virtualness" of properties more explicit, correct? We touch on a keyword and why we think it's suboptimal in the FAQ section. Unfortunately, I cannot think of many alternatives. The `$field` variable made it a bit more obvious, but only marginally. I do believe that, for the most part, the user should not have to think much about whether the property is backed or virtual. The behavioral differences are mostly intuitive. For example: ```php class Test { // This property has a set hook that writes to the backing value. Since // we're using the backing value, it makes sense for there to be a way = to // retrieve it. Without that, it wouldn't be useful. public $prop { set { $this->prop =3D strtoupper($value); } } // Similarly, a property with only a get hook that accesses the backing // value would need a way to write to the property for the get to be us= eful. public $prop { get =3D> strtoupper($this->prop); } // A property with a get hook that does not use the backing value does = not // need an implicit set operation, as writing to the backing value woul= d be // useless, given that nobody will read it. public $prop { get =3D> 42; } // Similarly, in the esoteric write-only case that does not use the bac= king // value, having an implicit get operation would always lead to a // "uninitialized property" error, and is not useful as such. public $prop { set { echo "Prop set\n"; } } } ``` Furthermore, `serialize`, `var_dump` and the other functions operating on raw property values will include the property only if it is backed. This also seems intuitive to me: If you never use the backing value, the backing value would always be uninitialized, so there's no reason to include it. One case that is not completely obvious is lazy-initialized properties. ```php class Test { public $prop { get =3D> $this->prop ??=3D expensiveOperation(); } } ``` It's not immediately obvious that there is a public set operation here. The correct way to fix this would be with asymmetric visibility, which was previously declined. Either way, I don't consider this case alone enough to completely switch our approach. Please let me know if you are aware of any other potentially non-intuitive cases. I will admit that it is unfortunate that a user of the property has to look through the hook implementation to understand whether a property is writable. As you have previously suggested, one option might be to add an explicit `set;` declaration. Maybe it's a bit more obvious now, after my previous e-mail, why we are trying to avoid this. Apart from the things already mentioned, it's unclear to me whether, with such `set;` declarations, a `get`-only backed property should even be legal. With the complete absence of a write operation, the assignment within the `set` itself would fail. To make this work, the absence of `set;` would need to mean something like "writable, but only within another hook", which introduces yet another form of asymmetric visibility. > > Dynamic properties are not particularly relevant today. The point was > > not to show how similar these two cases are, but to explain that > > there's an existing mechanism in place that works very well for hooks. > > We may invent some new mechanism to access the backing value, like > > `field =3D 'value'`, but for what reason? This would only make sense if > > the syntax we use is useful for something else. However, given that > > without guards it just leads to recursion, which I really can't see > > any use for, I don't see the point. > > I can think of several reasons we *could* explore other syntax: > > 1) To make it clearer in code whether a particular line is accessing via = the hooks, or by-passing them 2) To make the code in the hooks shorter (e.g= . `$field` is significantly shorter than `$this->someDescriptiveName`) 3) T= o allow code to by-pass the hooks at will, rather than only when called fro= m the hooks (e.g. having a single method that resets the state of several l= azy-loaded properties) > > Those reasons are probably not enough to rule out the current syntax; but= they show there are trade-offs being made. Fair enough. 1 and 2 are reasons why we added the `$field` macro as an alternative syntax in the original draft. I don't quite understand point 3. In Kotlin, `field` is only usable within its associated hook. Other languages I'm aware of do not provide a way to access the backing value directly, neither inside nor outside the accessor. > To be honest, my biggest hesitation with the RFC remains asymmetric types= (the ability to specify types in the set hook). It's quite a significant f= eature, with no precedent I know of, and I'm worried we'll overlook somethi= ng by including it immediately. For instance, what will be the impact on pe= ople using reflection or static analysis to reason about types? I would per= sonally be more comfortable leaving that to a follow-up RFC to consider the= details more carefully. I personally do not feel strongly about whether asymmetric types make it into the initial implementation. Larry does, however, and I think it is not fair to exclude them without providing any concrete reasons not to. I will spend time in the following days cleaning up tests, and I will try my best to try to break asymmetric types. If I (or anybody else) can't find a way to do so, I don't see a reason to remove them. > Nobody else has raised that, beyond the syntax; I'm not sure if that's be= cause everyone is happy with it, or because the significance has been overl= ooked. Yes, unfortunately that's a classic problem in RFC discussions: Syntax gets a disproportionate amount of attention. Ilija