Hi Rob, I'm going to respond to a few points from earlier emails here instead of each one.
On Sat, Jul 19, 2025 at 6:13 AM Rob Landers <rob@bottled.codes> wrote: > > > > On Sat, Jul 19, 2025, at 12:09, Claude Pache wrote: > > > > Le 19 juil. 2025 à 09:46, Rob Landers <rob@bottled.codes> a écrit : > > > > On Sat, Jul 19, 2025, at 03:04, Claude Pache wrote: > > > > > Le 19 juil. 2025 à 00:41, Rob Landers <rob@bottled.codes> a écrit : > > > The original author (Nikita) suggested that there's nothing in the original > design that precludes accessors -- and highlights languages where there are > both and they are doing just fine more than 5 years later. > > > Hi Rob, > > It is indeed entirely reasonable to have both readonly properties and hooked > properties (aka accessors), and today PHP has indeed both of them (and even > asymmetric visibility on top of that, as a separate feature contrarily to > C#). But it doesn’t mean that it is reasonable for the *same* property to be > *both* readonly and hooked, which is the point that is currently disputed. — > What do the other languages allow? Is it possible to define a readonly > property with a user-defined getter? (Disclaimer: Even if one of them allows > such a thing, I’ll still think that it is a bad idea.) I do not believe I was cherry picking; I share Claude's interpretation here that the RFC says that readonly doesn't prevent the language from adopting accessors (hooks) later, which is what the language did, and notably it did without applying them to readonly properties. Could you perhaps walk me through your thinking when the RFC claims that `assert($prop === $prop2)` "always holds"? > > —Claude > > > Hey Claude, > > From what I've seen in other languages, this combination is fairly common and > not inherently poblematic. > > - C# allows get hooks with user-defined logic, even in readonly structs. > - Kotlin uses val with a get() body, which is readonly from the consumer's > perspective, even though the value is computed. > - TypeScript allows a get-only accessor which acts readonly. > - Swift also allows get-only computed accessors/hooks. (disclaimer, I am not a C# expert) It seems that C# has both fields and properties, and a readonly field seems to align with what a few of us are claiming is how PHP readonly properties should work. C# properties are more open-ended, and don't actually support the readonly keyword - you can make them "read only" in the sense of only having a get accessor (and you can mark that accessor itself as readonly), but this is different from readonly fields, which enforce a contract about the mutability of the field. I think that C# fields, both readonly and not, match PHP's properties without hooks. C# properties - which I believe cannot be *marked* readonly, but they can be *made* read only, i.e. only exposing a get accessor - match PHP's properties with hooks. > > > Hi Rob, > > The main problem is that we don’t agree on the meaning of “readonly property”. I agree with Claude here. Rob, I'm curious how you interpret the contract of readonly. Do you think that it is a contract about writability to consumers of the class? In an earlier email, you said: > In the example above, there is nothing mutable about it. It is "read only" > from a public contract point-of-view, we just can't mark it as a readonly > class. In this most recent email, you said: > The error you get when trying to modify the "get-only accessor" is `Error: > Cannot assign to 'name' because it is a read-only property` > > Thus, readonly is implied by the get-only accessor, there's no need to > specify it directly. Would you say this is how you are interpreting readonly? That it is a contract to consumers of the class that they can read but cannot write to it? (including a snippet from an earlier email) > I think an init hook is out of the question for 8.5, so I'm not even sure > it's worth discussing. I don't agree that it's not worth discussing alternative solutions to the problems the RFC authors intend to solve. I think it has been expressed elsewhere, but I believe we should take the time to make the best decisions for the language and not rush to add a controversial feature.