Request for Comments: Alternative typehinting syntax for accessors
- Date: 2013-01-04
- Author: Nikita Popov nikic@php.net
- Status: Declined
Introduction
This RFC proposes a different typehinting syntax for the property accessors proposal. The proposed syntax places the typehint before the property name rather than in the set
accessor's parameter declaration. This optimizes a common use of accessor properties and aligns the syntax with other languages. In particular it will allow to typehint properties without specifying accessors (public DateTime $date;
).
Current syntax(es)
The current accessors RFC implements two syntax variations for accessors. The first is the original parentheses-less form using the magic $values
variable:
private $seconds; public $hours { get { return $this->seconds / 3600; } set { $this->seconds = $value * 3600; } }
The newly added second syntax allows specifying the accessors in a more function-like form:
private $seconds; public $hours { get() { return $this->seconds / 3600; } set($hours) { $this->seconds = $hours * 3600; } }
One of the reasons to add the latter syntax is to allow typehinting the setter. E.g. this allows to do something like the following:
public $date { get() { return $this->date; } set(DateTime $date) { $this->date = $date; } }
The $date
property implemented above behaves the same way as a normal property, but only allows to be assigned DateTime
instances. Using automatic accessors it is possible to implement the same with a bit less boilerplate:
public $date { get; set(DateTime $date); }
Typehinting
There is clear evidence that typehinting is of great importance to PHP developers. This doesn't only apply to ordinary methods, but also to accessors. An analysis of the Symfony 2.1 Standard Distribution 1) has shown that about a third of all setXYZ()
-style methods are typehinted. About 15% of the setters are actually only typehinting and don't perform any other action than enforcing the typehint.
Thus the main objective of this proposal is to improve the typehinting aspect of the accessors proposal.
Proposed syntax
This RFC proposes to change the current syntax for typehinted accessors...
public $date { get() { return $this->date; } set(DateTime $date) { $this->date = $date; } }
... by moving the typehint in front of the property name:
public DateTime $date { get { return $this->date; } set { $this->date = $value; } }
Automatic accessors can be used to reduce the boilerplate:
public DateTime $date { get; set; }
Which again is equivalent to just the property with the typehint:
public DateTime $date;
Default values and nullability
When the shorthand public Type $name;
syntax is used it will be possible to specify a default value (something that is not normally possible with accessors). The default value will use the same syntax and semantics as function parameter typehints. For example the following specifies an array
property with an array default value:
public array $foo = [1, 2, 3];
The nullability semantics are also the same as with parameter typehints:
public DateTime $date; // can not assign null public DateTime $date = null; // can assign null
Note that properties are null
initialized by default. The nullability semantics do not (and can not) affect this. They only specify whether it's possible to assign null
to the property after initialization.
Default values can only be used on the shorthand notation. If accessor methods are specified a default value can not be used. The only exception is the = null
default, which can still be used to specify nullability:
public DateTime $date = null { get { ... } set { ... } }
Benefits of the proposed syntax
The proposed syntax has several benefits over the current syntax, with the main one being that it optimizes a very common use case (while not making other use cases worse). As mentioned above about 15% of all accessor methods in Symfony would be able to use the public DateTime $date
style shorthand notation. Furthermore this proposal allows a default value to be specified for typehinted properties.
Even when the shorthand can not be used (because one actually defines some accessors) I would argue that the proposed syntax is more elegant than the current one, mainly because the relevant API information is focused at one point at the start of the declaration. For interacting with the class only the visibility and the typehint are of importance, whereas the actual implementation is irrelevant. The public DateTime $date { ... }
syntax does a better job at conveying the relevant bits than the current syntax:
public $date { // <-- This is important get { // Some // Rather // Long // Code } set(DateTime $date) { // <-- And the typehint here is important, too // Some // Further // Code // Here } }
Another benefit I see in this typehint syntax is that most programmers are already familiar with it, because virtually every strongly typed language uses it. Most dynamic languages with support for optional typing that I know (like Dart or TypeScript) also use this syntax. This makes the syntax a lot more intuitive. If you want to typehint a property your first try will probably be putting the typename in front of it, rather than coming up with something like public $date { get; set(DateTime $date); }
. I think the latter syntax isn't particularly hard to understand *once you know it*, but it's not something that comes up intuitively.
One last benefit that comes from this syntax is that we no longer need two ways to specify accessors (with and without parentheses). Though I also heard the opinion from some people that both syntaxes should be still kept to avoid the $value
magic variable. I'd probably be okay either way, but I personally dislike it if there are two very similar ways to do one thing.
Common Misconceptions
When I brought this up last time the discussion showed some misconceptions regarding this proposal. This seems to be inherent to any discussion involving typehints in some way, so I decided to clear some things up beforehand.
The important thing to realize is that this proposal does not add new typehinting concepts to PHP. It's just suggests a more general, more convenient and more familiar syntax for what already exists in the accessors proposal. The public DateTime $date;
syntax is exactly equivalent to the following snippet using the current syntax:
public $date { get; set(DateTime $date); }
The last time I brought this up most of the discussion focused on the question whether typehints in PHP are a good idea in general and I would like to prevent this kind of discussion this time, as it is only tangentially related. Fact is that we do have typehints for methods and that those typehints are used a lot. Fact is that the typehints are also used a lot on accessors (30%) and often *just* for the typehint (15%). Fact also is that the accessors proposal makes the normal method typehints apply to properties. So the question really isn't whether typehints on properties are a good idea, the question is rather whether we want to have the convoluted public $date { get; set(DateTime $date); }
syntax all over the code or the familiar and clearer public DateTime $date;
syntax.
I understand that some people on internals disapprove of typehints in general and that they have reasons to do so. I hope that those people will be able to consider this without prejudice and on its actual merits concerning the actual use of the language. Thanks.
Patch
The patch for this proposal is available here: https://gist.github.com/4579298. You can find the individual commits here: https://github.com/nikic/php-src/commits/alternativeSyntax.
Voting
This proposal depends on the main accessors RFC. The result of this vote is only relevant if the main RFC is accepted. As this is a language change it requires a 2/3 majority.
The vote ended 3 in favor, 12 against, as such this feature is declined.