It's okay to vote against this if cloning is a deal breaker. In that case
I'll probably either work on cloning before re-proposing this, or pivot to
asymmetric visibility -- it's not my first preference, but it may be the
more pragmatic choice. Cloning is definitely the weak point of this
proposal.I already went through the clone-arguments mental exercise in my earlier analysis, and the code
it produces is totally disgusting. :-) clone-with is a considerably better approach if you're starting
from readonly. (It's also better if you start from asymmetric visibility, although that version needs
a clone-help feature far less.)
Internals have been here before, it's a recurring problem in PHP that
fundamentally missing features are voted down because people want
other complementary features first.
read only has been voted down by people rather wanting type properties
first, or rather wanted assessors first. And then in turn accessors
multiple times were voted down by the other 2 camps. But these
features are interconnected and need to be done step by step, during
the process things won't be perfect either way,
Now we have read only vs clone with vs accessors vs ...
IMO problem caused by no clear roadmap / vision of the project that
people can be united behind.
--
Anyway, even though I tried to push for asymmetric visibility last
year I'd gladly vote +1 on this.
It's not perfect, but it's the right direction, and there are multiple
starting points to get there.
This solves 80-90% of the use cases out there for read only
properties, which is a very good start.
--
Nikita: Probably a small thing, but the only detail I'm unsure of is
why focus on write-once logic? Why not aim for aligning it with a
future *:init visibility, where I would think the property in PHP
should be writable in __construct(), __destruct() and __clone().
This won't solve the separate clone with feature request. But it would
make it more flexible and language design wise would set it up for
possible asymmetric visibility + init option later.
For now it would at least allow setting default values on the
property, for instance if argument to constructor is not 1 to 1 with
property type/value and needs some light logic in __construct to
determine if property should be set to something else then default.
But again, don't see a blocker here in current RFC, as it starts out
with a narrow scope of read only, and this can be widened later.
On Wed, Jun 30, 2021 at 10:36 AM André Rømcke andre.romcke@gmail.com
wrote:
It's okay to vote against this if cloning is a deal breaker. In that
case
I'll probably either work on cloning before re-proposing this, or
pivot to
asymmetric visibility -- it's not my first preference, but it may be
the
more pragmatic choice. Cloning is definitely the weak point of this
proposal.I already went through the clone-arguments mental exercise in my earlier
analysis, and the code
it produces is totally disgusting. :-) clone-with is a considerably
better approach if you're starting
from readonly. (It's also better if you start from asymmetric
visibility, although that version needs
a clone-help feature far less.)Internals have been here before, it's a recurring problem in PHP that
fundamentally missing features are voted down because people want
other complementary features first.read only has been voted down by people rather wanting type properties
first, or rather wanted assessors first. And then in turn accessors
multiple times were voted down by the other 2 camps. But these
features are interconnected and need to be done step by step, during
the process things won't be perfect either way,Now we have read only vs clone with vs accessors vs ...
IMO problem caused by no clear roadmap / vision of the project that
people can be united behind.--
Anyway, even though I tried to push for asymmetric visibility last
year I'd gladly vote +1 on this.
It's not perfect, but it's the right direction, and there are multiple
starting points to get there.This solves 80-90% of the use cases out there for read only
properties, which is a very good start.--
Nikita: Probably a small thing, but the only detail I'm unsure of is
why focus on write-once logic? Why not aim for aligning it with a
future *:init visibility, where I would think the property in PHP
should be writable in __construct(), __destruct() and __clone().This won't solve the separate clone with feature request. But it would
make it more flexible and language design wise would set it up for
possible asymmetric visibility + init option later.For now it would at least allow setting default values on the
property, for instance if argument to constructor is not 1 to 1 with
property type/value and needs some light logic in __construct to
determine if property should be set to something else then default.But again, don't see a blocker here in current RFC, as it starts out
with a narrow scope of read only, and this can be widened later.
Yes, this is a possible alternative interpretation of the readonly concept.
The current proposal is closer to how Java final variables work, which
never allow reassignment, while your suggestion is closer to C# readonly,
which does allow reassigning in the constructor.
I went with the current proposal, because it integrates nicely with the
initialization concept introduced by typed properties. At the time, we also
had lots of discussions about how typed property initialization should
work, and requiring that all typed properties be initialized by the end of
the constructor was one of the contenders. However, we ultimately decided
against such an approach, because it does not integrate well with other
aspects of the language. In particular we need to have the ability to
initialize an object while bypassing the constructor, and we don't have the
ability to determine initialization statically, so an uninitialized state
would have been required in any case.
If we had gone with that alternative initialization model at the time, then
we would also use the same one for readonly properties. But that's not how
things work now. Doing something like this now would require introducing an
entirely new scoping concept. This brings up awkward questions like: How do
you bind a closure to this new "initialization scope"? Closure rebinding is
a common way to bypass visibility restrictions. What happens if you want to
call a helper method to do the initialization, does that still count as
initialization scope? What if you call $object->__construct() directly,
will that allow changing properties?
The current proposal tries to provide a simple, absolute guarantee: Once
initialized, the property will never change again. I think that makes the
feature easy to understand and reason about.
Regards,
Nikita
Yes, this is a possible alternative interpretation of the readonly concept. The current proposal is closer to how Java final variables work, which never allow reassignment, while your suggestion is closer to C# readonly, which does allow reassigning in the constructor.
I went with the current proposal, because it integrates nicely with the initialization concept introduced by typed properties. At the time, we also had lots of discussions about how typed property initialization should work, and requiring that all typed properties be initialized by the end of the constructor was one of the contenders. However, we ultimately decided against such an approach, because it does not integrate well with other aspects of the language. In particular we need to have the ability to initialize an object while bypassing the constructor, and we don't have the ability to determine initialization statically, so an uninitialized state would have been required in any case.
If we had gone with that alternative initialization model at the time, then we would also use the same one for readonly properties. But that's not how things work now. Doing something like this now would require introducing an entirely new scoping concept. This brings up awkward questions like: How do you bind a closure to this new "initialization scope"? Closure rebinding is a common way to bypass visibility restrictions. What happens if you want to call a helper method to do the initialization, does that still count as initialization scope? What if you call $object->__construct() directly, will that allow changing properties?
The current proposal tries to provide a simple, absolute guarantee: Once initialized, the property will never change again. I think that makes the feature easy to understand and reason about.
Thanks for the detailed explanation, I'm sold!
And it seems it can evolve further once complementary features are introduced.