Good morning Internals,
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:
https://wiki.php.net/rfc/property_write_visibility
This enables readonly, write-only and immutable like semantics for PHP's
properties.
These are the common use cases where users tend to resort to magic methods
or setter/getter
methods. This proposal will as such avoid unnecessary boilerplate, makes
coding easier and more
ergonomic, and in the case of magic method usage improve performance.
Best,
André Rømcke
On Mon, Jun 29, 2020 at 12:42 PM André Rømcke andre.romcke@gmail.com
wrote:
This enables readonly, write-only and immutable like semantics for PHP's
properties.
I agree that there is a use case for it, however I don't think the proposed
syntax public:private
is intuitive. Maybe we can come up with something
better?
--
Best regards,
Max Semenik
I don't dislike the syntax and I think I can get used to it extremely fast,
tbh. Are there any other languages that have a similar syntax? Has any
other language syntax been considered?
On Mon, Jun 29, 2020 at 12:42 PM André Rømcke andre.romcke@gmail.com
wrote:This enables readonly, write-only and immutable like semantics for PHP's
properties.I agree that there is a use case for it, however I don't think the proposed
syntaxpublic:private
is intuitive. Maybe we can come up with something
better?--
Best regards,
Max Semenik
--
Marco Aurélio Deleu
man. 29. jun. 2020 kl. 12:06 skrev Deleu deleugyn@gmail.com:
Are there any other languages that have a similar syntax? Has any other
language syntax been considered
The only one I could find that matches is Swift:
public private(set) var numberOfEdits = 0
https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html#ID18
Beyond that there are some notable related examples:
C#
public readonly Color Black = new Color(0, 0, 0);
The semantics of readonly is closer to what we refer to as immutable here:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#readonly-fields
If you want other semantics in C# you'll need to resort to Accessors:
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/classes#accessors
Rust:
// This field can be read (but not written) by super.
#[readonly]
pub(super) readable: i32,
Essentially a feature using "attributes":
https://docs.rs/readonly/0.1.6/readonly/
--
Best
André Rømcke
I agree that there is a use case for it, however I don't think the
proposed syntaxpublic:private
is intuitive. Maybe we can come up with
something better?
Would something closer to Swift be better? If so I expanded the RFC with
that syntax option as well:
class User {
public private(set) int $id;
public protected(set) string $name;
public function __construct(int $id, string $name) {
$this->id = $id;
$this->name = $name;
}}
Would something closer to Swift be better? If so I expanded the RFC with
that syntax option as well:
Borrowing from the various accessors RFCs:
public int $x {
protected set;
protected unset;
}
Then a future RFC can build upon it by adding the override functions
while keeping the same base syntax.
Mark Randall
I'd like this feature as a stop-gap for accessors.
However, I don't like the syntax at all, I couldn't reasonably vote for
it in its current suggested state. I think it's just too messy.
I'm not sure what the alternative should be though. It seems like the
accessor syntax would be the only long-term clean way.
Mark Randall
Hey André,
This does indeed seem to cut into the traditional property accessors scope.
I'm no longer seeing a reason to have property accessors, since immutable
state (and promotion thereof) is much more relevant to fight bugs and
improve application performance and maintainability.
Therefore, I would endorse re-visiting the RFC at
https://wiki.php.net/rfc/write_once_properties instead.
Máté also linked today (
https://twitter.com/kocsismate90/status/1277625002720968704) that C# 9.0 is
getting init-only properties, which looks similar to the RFC linked above.
Assuming we solve annoyances around cloning, that would be a more sensible
way forward, while property accessors seem to perpetuate the bad practice
of getters and setters, which are the main cause for me having to fire up a
debugger in any environment.
Marco Pivetta
On Mon, Jun 29, 2020 at 11:42 AM André Rømcke andre.romcke@gmail.com
wrote:
Good morning Internals,
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:https://wiki.php.net/rfc/property_write_visibility
This enables readonly, write-only and immutable like semantics for PHP's
properties.These are the common use cases where users tend to resort to magic methods
or setter/getter
methods. This proposal will as such avoid unnecessary boilerplate, makes
coding easier and more
ergonomic, and in the case of magic method usage improve performance.Best,
André Rømcke
property accessors seem to perpetuate the bad practice
of getters and setters
Outside of access restrictions, a common use case I've seen for property
accessors is lazy-loading, which I know is something you use in other forms.
Máté also linked today (
https://twitter.com/kocsismate90/status/1277625002720968704) that C# 9.0 is
getting init-only properties, which looks similar to the RFC linked above.
Note that in C# the new "init" keyword is explicitly an extension of
property accessors [1], and relates specifically to "object initializers",
which PHP does not have; a proposal for them last year [2] was rejected.
An existing "readonly" keyword [3] allows you to write a variable only in
the constructor, and "init" is mostly needed because object initializers
are run too late for this.
C# 9.0 also has a bunch of features around immutable data structures in
general, including a variant of object initializers called
"with-expressions" [4] to solve the "modified clone" problem.
[1]
https://github.com/dotnet/csharplang/blob/master/proposals/init.md#detailed-design
[2] https://wiki.php.net/rfc/object-initializer
[3]
https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/readonly
[4] https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/#with-expressions
--
Rowan Tommins
[IMSoP]
Hey Rowan,
property accessors seem to perpetuate the bad practice
of getters and settersOutside of access restrictions, a common use case I've seen for property
accessors is lazy-loading, which I know is something you use in other
forms.
I had already tested the write-once properties RFC with lazy-loading: works
just fine ?
Hey Rowan,
On Mon, Jun 29, 2020, 18:19 Rowan Tommins <rowan.collins@gmail.com
mailto:rowan.collins@gmail.com> wrote:On Mon, 29 Jun 2020 at 16:44, Marco Pivetta <ocramius@gmail.com <mailto:ocramius@gmail.com>> wrote: > property accessors seem to perpetuate the bad practice > of getters and setters > Outside of access restrictions, a common use case I've seen for property accessors is lazy-loading, which I know is something you use in other forms.
I had already tested the write-once properties RFC with lazy-loading:
works just fine ?
I meant that property accessors can be used to implement lazy-loading,
removing the need for magic methods and dynamic references to variables,
e.g.:
class Whatever {
private string $_name;
public string $name {
get {
if( ! isset($_name) ) { $this->loadData(); }
return $this->_name;
}
}
}
Regards,
--
Rowan Tommins (né Collins)
[IMSoP]
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:https://wiki.php.net/rfc/property_write_visibility
This enables readonly, write-only and immutable like semantics for PHP's
properties.These are the common use cases where users tend to resort to magic methods
or setter/getter
methods. This proposal will as such avoid unnecessary boilerplate, makes
coding easier and more
ergonomic, and in the case of magic method usage improve performance.
Thanks, André,
I really like it. I feel like it perfectly fits the runtime visibility
model of PHP. The RFC could have some words to tell how this would behave
when considering the existing magic accessors. We should also define the
behavior when creating a reference (write access should be granted, isn't
it?) and when unsetting a property.
I'd like to share three more points to the discussion:
The previous RFC(s) shocked on a conflict between purity declarations
(immutable/readonly) and the effective need for mutability in e.g. cloning
operations. My experience in PHP is that keywords are strong guidelines but
should never be hard blockers: PHP is a runtime scripting language and some
of its power and flexibility comes from that, e.g. being able to use
reflection sometime to read/write a property in a "friend" scope. "final"
is the canonical contra-example of an imperative keyword that blocks legit
use cases (e.g. inheritance proxies)
I understand why some ppl want immutable/readonly hard guarantees. I think
those are nice goals, and I also think that they are better solved by
attributes/annotations. These features fit compiled languages. In PHP, they
fit static analyzers. There are great ones already and they do a really
good job.
In other answers, I'm seeing questions about private(isset)/private(unset)
in addition to just read+write dissociation. I'm not sure this makes sense:
once a property is declared, "isset-accessibility" is fully covered by
"read-accessibility". Same for "unset-accessibility": it's included in
"write-accessibility". Clarifying how magic accessors would work in the RFC
should help solve this branch of the discussion.
About accessors, they look like another topic to me. I'm not seeing the
need for accessors at all actually. You might disagree, but my point is:
that's another topic. We don't need to agree on the usefulness of accessors
to decide that this RFC provides actionable value that would benefit the
ecosystem.
Being able to enforce an externally-immutable-but-internally-mutable state
is already a lot of value, I know where I would leverage it immediately.
About the syntax, the proposed one looks quite effective to me. It's new,
we need to get used to it. This should come fast given how simple it is.
TL;DR, I fully support the RFC :)
Nicolas
Good morning Internals,
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:
Perhaps another option could be to use attributes:
<<ReadOnly>>
public int $id;
Assuming named arguments get accepted as well, we could use optional
arguments to specify special behavior by writing:
<<ReadOnly(protected: True)>>
public int $id;
These optional arguments could also be introduced later using a followup
RFC, after introducing a basic ReadOnly attribute.
This attribute-based approach could be extended later to implement
property accessors. That would provide property accessors similar to how
it is done in Python:
<<Property>>
public function someValue(): int
{
return $this->someValue;
}
which could then be accessed as:
$instance->someValue
The above accessor method would be the equivalent of:
<<ReadOnly>>
public int $someValue;
That makes the ReadOnly attribute a short hand for the Property
attribute. This short hand is something that Python does not have, by
the way.
Using accessor attributes to create a writable property could look like
this:
<<PropertySetter>>
public function someValue(int $newValue)
{
$this->someValue = $newValue;
}
Making the property writable only in the protected or private scope
could be done by using the existing mechanism of declaring the accessor
method as protected or private.
So perhaps an attribute-based approach provides a nice alternative path
for gradually improving object ergonomics.
Regards,
Dik Takken
Perhaps another option could be to use attributes:
<<ReadOnly>>
public int $id;
I’d actually also like a syntax like that as well for ReadOnly and
Immutable in the end.
It's more readable and it would be possible to annotate on the class level
as well (to affect all properties).
So I initially explored* in this direction, however if we go that way first
we'll likely end up with any reflection code
having to deal with attributes and understand their underlying visibility
semantics.
If we rather go this route of first introducing the concept of disconnected
visibility. The reflection API is
far clearer / understandable, more future proof, and adding the attributes
as immediate syntax sugar
followup is far more straightforward.
- initial explorative draft rfc:
https://wiki.php.net/rfc/readonly_and_immutable_properties
I do agree with Marco that this is a step in a wrong direction. Our
goal should be not ensuring that a prop is not rewritten outside, but
rather that it is not re-written at all. It makes no sense to rewrite
a property in majority of cases:
- fields of an DTO - nay. Should be immutable instead. You never
change DTO, don't you? - injected services (like DB connection or an HTTP client) - nay.
Shouldn't ever be overwritten once an object containing them is
instantiated. Write-once / immutable is preferred. - data fields of an Entity-like object - looks like the only
reasonable case. However adding dedicated syntax for this is arguably
not much better that what we have now. It is already solvable with
standard getX() pattern, or with a single method returning a required
chunk of state as DTO.
So for me this does only solve the problem of having getters (or
dedicated methods) in #3, which is rare enough compared to other code,
and is already solvable with syntax existing nowadays already.
Introducing the new syntax, however, will have the following
downsides:
- adding proper immutable / write-once properties to the language will
be met with much more resistance: "Why adding immutable if we have
private set already!" - this will encourage using them in places where immutability (e.g.
via static analysis tool like Psalm) should be used instead (see #1
and #2). - adding more advanced property accessors feature will be also likely
met with more resistance.
On Mon, Jun 29, 2020 at 11:43 AM André Rømcke andre.romcke@gmail.com
wrote:
Good morning Internals,
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:https://wiki.php.net/rfc/property_write_visibility
This enables readonly, write-only and immutable like semantics for PHP's
properties.These are the common use cases where users tend to resort to magic methods
or setter/getter
methods. This proposal will as such avoid unnecessary boilerplate, makes
coding easier and more
ergonomic, and in the case of magic method usage improve performance.
I think this is a good direction to explore, but would recommend delaying
it until PHP 8.1. As the RFC and discussion note, the design space here
overlaps significantly with both readonly/immutability and property
accessors. We should take enough time to consider these
alternatives/extensions as well, to ensure that we don't end up with
multiple distinct and possibly incompatible mechanisms. We don't have that
time before PHP 8.0 feature freeze.
Regards,
Nikita
ergonomic, and in the case of magic method usage improve performance.
I think this is a good direction to explore, but would recommend delaying
it until PHP 8.1. As the RFC and discussion note, the design space here
overlaps significantly with both readonly/immutability and property
accessors. We should take enough time to consider these
alternatives/extensions as well, to ensure that we don't end up with
multiple distinct and possibly incompatible mechanisms. We don't have that
time before PHP 8.0 feature freeze.
I've updated the RFC to rather aim for 8.1, I fully agree this should in
any form be made asure to align well with the related requests. Larrye's
email is a good example of what kind the language might look like when
several such features are potentially accepted in the future.
May I propose that some of us interested in this do a short call over the
summer on this topic to see if we can align on direction?
ergonomic, and in the case of magic method usage improve performance.
I think this is a good direction to explore, but would recommend delaying
it until PHP 8.1. As the RFC and discussion note, the design space here
overlaps significantly with both readonly/immutability and property
accessors. We should take enough time to consider these
alternatives/extensions as well, to ensure that we don't end up with
multiple distinct and possibly incompatible mechanisms. We don't have that
time before PHP 8.0 feature freeze.I've updated the RFC to rather aim for 8.1, I fully agree this should in
any form be made asure to align well with the related requests. Larrye's
email is a good example of what kind the language might look like when
several such features are potentially accepted in the future.May I propose that some of us interested in this do a short call over the
summer on this topic to see if we can align on direction?
I'm open to that. Explicit design process FTW.
--Larry Garfield
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:
From the RFC:
"Attempting to pass a property value outside of allowed writable scope
as a reference, results in an error."
This part could probably do with having some details for it.
Also, any implementation of that rule might need to be checked for
performance issues.
cheers
Dan
Ack
I'd like to start discussion on a new RFC proposing a way to be able to
(optionally) specify property
write visibility, separate from read:From the RFC:
"Attempting to pass a property value outside of allowed writable scope
as a reference, results in an error."This part could probably do with having some details for it.
Also, any implementation of that rule might need to be checked for
performance issues.
I think it would be technically possible, by extending the existing
mechanism for references to typed properties. However, we definitely
shouldn't do this, because it goes against existing language semantics. You
can take a reference to a normal private property (i.e. private get,
private set), pass it outside the class and then modify it. It would be
inconsequent to assign stricter semantics to a weaker visibility
requirement (public get, private set).
Regards,
Nikita