On Sun, Feb 23, 2020, at 2:39 AM, Mike Schinkel wrote: > > On Feb 21, 2020, at 6:17 PM, Larry Garfield <la...@garfieldtech.com> wrote: > > I'm totally on board for better value object support, so that's a good > > motive for me. The question I have is whether this is really a good > > stepping stone in that direction or if it would lead down a wrong path and > > lock us into too much TIMTOWTDI (for the Perl fans in the room). So let's > > think that through down that path. How would write-once properties lead > > into properly immutable value objects? Or do they give us that themselves? > > > > The biggest challenge for immutable objects, IMO, is evolving them. Eg, > > $result->withContentType(...) to use the PSR-7 example. Would we expect > > people to do it with a method like that, or would there be some other > > mechanism? If the properties are public, would we offer a more syntactic > > way to modify them directly? > > > > 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. > > > > My other concern is a public property (the most likely use case) would have > > to be set in the constructor. If it's not, then callers cannot rely on it > > having been set yet if it's set lazily. And if code inside the class tries > > to set it lazily, it may already have been set by some external code > > (rightly or wrongly) and cause a failure. > > > > > How do we address that? There's absolutely use cases where setting > > everything in the constructor ahead of time is what you'd do anyway, but > > there are plenty where you wouldn't want to, either, which creates a race > > condition for who sets it first, or tries to access it before it gets set, > > etc. (This is where my repeated questions about lazy initialization come > > from.) > > > I have struggled to follow this RFC thread fully, so if I am getting > something out of context, please note that and I apologize in advance. > > However, it would see that rules for `write once` properties to support > lazy loading would be rather simple: > > 1. Write-once properties can only be updated once. > 2. Write-once properties can only be updated within the class where > they are declared.
This is the common use case I think many envision, but nothing in the proposal requires that. A public write-once property (as currently written) would be world-readable, and world-writeable, once. Separate visibility for internal and external access is a separate matter. (Also potentially useful, but not part of the write-once proposal at the moment.) > 3. If you want to update a property from outside the class, create a > set_<property>() method to allow it to happen. > 4. If you do not want it to be set externally, do not implement a > set_<property>() method. > 5. If you want it to be implemented externally sometimes but not > others, implement guard classes inside the set_<property>() method. > > I think that addresses all scenarios, no? > > -Mike It does not. 1) Race condition if I assume that a public write-once property is a materialized value, but access it before it gets materialized. 2) Race condition if internal non-constructor code wants to set the value, but some external routine has set it first. 3) Cloning creates an interesting and complicated case of both of the above. Does a cloned object start with its write-once bits reset or no? There's problems both ways. Making a write-once property implicitly write-only-from-inside-the-class would help address point 2, but not points 1 or 3. Adding separate get/set visibility modifiers is another interesting idea, but is separate and should be evaluated on its own merits. It is not at this time part of this proposal. --Larry Garfield -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php