Proposal fo "Code-free constructors declaration"

php.internals

Andrey O Gromov

7 years ago
Full description https://wiki.php.net/rfc/code_free_constructor Draft realisation https://github.com/php/php-src/compare/master...rjhdby:constructor "Code free" constructor is constructor with only purpose to directly set object properties from received parameters and, optionally, call parent constructor. Main idea is to move such constructor declaration inside class declaration. Simple example: Current syntax class A extends B{ public $prop; public function __construct($prop){ parent::__construct("BlaBla", $prop); $this->prop = $prop; } } Proposed syntax class A($prop) extends B("BlaBla", $prop) { } With respect, Andrey.

Ivan Enderlin @ Hoa

7 years ago
On 23.01.19 13:32, Andrey O Gromov wrote:
> Full description > https://wiki.php.net/rfc/code_free_constructor > Draft realisation > https://github.com/php/php-src/compare/master...rjhdby:constructor > > "Code free" constructor is constructor with only purpose to directly set > object properties from received parameters and, optionally, call parent > constructor. > > Main idea is to move such constructor declaration inside class > declaration. > > Simple example: > > Current syntax > class A extends B{ > public $prop; > > public function __construct($prop){ > parent::__construct("BlaBla", $prop); > $this->prop = $prop; > } > } > > Proposed syntax > class A($prop) extends B("BlaBla", $prop) { > } > > With respect, Andrey.
Hello and thanks for the RFC. I don't like the approach but I can change my mind. Currently, I see an issue with your RFC: How do you add types with this syntax? Given this syntax from the RFC: class MotorCycle($vendor, $cc){     public $whells = 2;     //other methods }; class MyCustomMotorCycle($cc, $whells) extends MotorCycle("Custom", $cc){ }; How do you say that `public $cc` can be an integer for instance, so expressing this `public int $cc`? Cheers.

Weirdan

7 years ago
On Wed, Jan 23, 2019 at 2:32 PM Andrey O Gromov <AGromov@alfabank.ru> wrote:
> Proposed syntax > class A($prop) extends B("BlaBla", $prop) { > }
Would this work with anonymous classes? If so, how would the syntax look like?

Andrey O Gromov

7 years ago
>> Proposed syntax >> class A($prop) extends B("BlaBla", $prop) { >> }
>Would this work with anonymous classes? If so, how would the syntax look
like? Currently this syntax can't be used with anonymous classes because those classes instantiated at once they declared and same syntax is used for forwarding parameters directly into constructor. new class(10) extends SomeClass implements SomeInterface { public function __construct($num) {...} } I think that it is possible to create additional rule when use "parameter_list" instead of "argument_list". Some research is required. But it will add some ambiguity when reading code.

Levi Morrison

7 years ago
On Wed, Jan 23, 2019 at 6:57 AM Bruce Weirdan <weirdan@gmail.com> wrote:
> > On Wed, Jan 23, 2019 at 2:32 PM Andrey O Gromov <AGromov@alfabank.ru> wrote: > > > Proposed syntax > > class A($prop) extends B("BlaBla", $prop) { > > } > > Would this work with anonymous classes? If so, how would the syntax look like?
I have the same question. I don't think it would work with them, but I could be wrong.

Levi Morrison

7 years ago
On Wed, Jan 23, 2019 at 8:43 AM Levi Morrison <levim@php.net> wrote:
> > On Wed, Jan 23, 2019 at 6:57 AM Bruce Weirdan <weirdan@gmail.com> wrote: > > > > On Wed, Jan 23, 2019 at 2:32 PM Andrey O Gromov <AGromov@alfabank.ru> wrote: > > > > > Proposed syntax > > > class A($prop) extends B("BlaBla", $prop) { > > > } > > > > Would this work with anonymous classes? If so, how would the syntax look like? > > I have the same question. I don't think it would work with them, but I > could be wrong.
Ah, another message confirmed it but it hit my spam folder: it does not work with anonymous classes. In my opinion that is a non-starter.

Dan Ackroyd

7 years ago
On Wed, 23 Jan 2019 at 12:32, Andrey O Gromov <AGromov@alfabank.ru> wrote:
> > Full description > https://wiki.php.net/rfc/code_free_constructor > Draft realisation > https://github.com/php/php-src/compare/master...rjhdby:constructor >
If this RFC solves a big problem for you, I would strongly recommend looking at solving it with a preprocessor first: https://preprocess.io/ cheers Dan Ack

Stas Malyshev

7 years ago
Hi!
> Proposed syntax > class A($prop) extends B("BlaBla", $prop) { > }
This looks like unobvious magic. PHP approach has traditionally been to avoid unobvious magic, and be explicit about what is happening. This functionality does not seem no be enabling anything different, and seems to be pretty obscure as to what is going on. Also, $prop can not be documented this way, and assigning default value to it may be a bit weird too. I am all for paving the walkways, but this particular case seems to be a bit too narrow to have a special language syntax for, and the syntax seems to be not exactly obvious as to what's going on there.
-- Stas Malyshev smalyshev@gmail.com

Andrey O Gromov

7 years ago
I'm added an illustration. Maybe it more clear for understanding. https://wiki.php.net/_detail/rfc/joined.png?id=rfc%3Acode_free_constructor
>> Proposed syntax >> class A($prop) extends B("BlaBla", $prop) { >> }
> This looks like unobvious magic. PHP approach has traditionally been to > avoid unobvious magic, and be explicit about what is happening. > This functionality does not seem no be enabling anything different, > and seems to be pretty obscure as to what is going on.
There is no magic, just alternative constructor syntax with some default behavior. Additional paragraph in documentation will resolve all obscurity. Vice versa, this syntax make behavior more strict. No need to read constructor's body, because you know exactly what's going on. Also there is no place for typos in boilerplate and refactoring errors. IMHO inheritance also is more clear, because no need to search "parent::__construct" in the middle of class body.
> Also, $prop can not be documented this way, and assigning default > value to it may be a bit weird too.
Not sure that I understand this remark right way. What did you mean? You can use php-doc similar you used it for functions. Parameters block identical to function parameters block, including types and default values.
> I am all for paving the walkways, but this particular case > seems to be a bit too narrow to have a special language syntax for, and > the syntax seems to be not exactly obvious as to what's going on there.
Matter of quality of documentation. ---------------------------- To Levi Morrison and Bruce Weirdan.
>> Would this work with anonymous classes? If so, how would the syntax
look like?
> I have the same question. I don't think it would work with them, but I > could be wrong.
There is no big problem to add same functionality to anonymous classes. But unfortunately only possible syntax(I think) is not very nice. new class(string $a, int $b, int $c=15)("Hi!", 20) extends SomeClass($a, 115){...}

Nikita Popov

7 years ago
On Wed, Jan 23, 2019 at 1:33 PM Andrey O Gromov <AGromov@alfabank.ru> wrote:
> Full description > https://wiki.php.net/rfc/code_free_constructor > Draft realisation > https://github.com/php/php-src/compare/master...rjhdby:constructor > > "Code free" constructor is constructor with only purpose to directly set > object properties from received parameters and, optionally, call parent > constructor. > > Main idea is to move such constructor declaration inside class > declaration. > > Simple example: > > Current syntax > class A extends B{ > public $prop; > > public function __construct($prop){ > parent::__construct("BlaBla", $prop); > $this->prop = $prop; > } > } > > Proposed syntax > class A($prop) extends B("BlaBla", $prop) { > } > > With respect, Andrey.
Two alternatives you might want to consider: * https://wiki.php.net/rfc/automatic_property_initialization => Proposed function public function __construct(int $this->x, int $this->y) {}, which avoids the need for explicit property assignments in the ctor. However, the property still needs to be declared separately. * https://docs.hhvm.com/hack/other-features/constructor-parameter-promotion => Uses public function __construct(public int $x, public int $y) {} to declare properties in-line in the constructor. I think that *if* we want to add some kind of sugar of this type, then I'd strongly prefer the syntax used by Hack than the one proposed here. It makes a lot more sense to me intuitively, probably because the property declarations still looks like normal property declarations, they just occur in-line in the ctor. Nikita

Nikita Popov

7 years ago
On Fri, Jan 25, 2019 at 11:44 AM Nikita Popov <nikita.ppv@gmail.com> wrote:
> On Wed, Jan 23, 2019 at 1:33 PM Andrey O Gromov <AGromov@alfabank.ru> > wrote: > >> Full description >> https://wiki.php.net/rfc/code_free_constructor >> Draft realisation >> https://github.com/php/php-src/compare/master...rjhdby:constructor >> >> "Code free" constructor is constructor with only purpose to directly set >> object properties from received parameters and, optionally, call parent >> constructor. >> >> Main idea is to move such constructor declaration inside class >> declaration. >> >> Simple example: >> >> Current syntax >> class A extends B{ >> public $prop; >> >> public function __construct($prop){ >> parent::__construct("BlaBla", $prop); >> $this->prop = $prop; >> } >> } >> >> Proposed syntax >> class A($prop) extends B("BlaBla", $prop) { >> } >> >> With respect, Andrey. > > > Two alternatives you might want to consider: > > * https://wiki.php.net/rfc/automatic_property_initialization => Proposed > function public function __construct(int $this->x, int $this->y) {}, which > avoids the need for explicit property assignments in the ctor. However, the > property still needs to be declared separately. > > * > https://docs.hhvm.com/hack/other-features/constructor-parameter-promotion > => Uses public function __construct(public int $x, public int $y) {} to > declare properties in-line in the constructor. > > I think that *if* we want to add some kind of sugar of this type, then I'd > strongly prefer the syntax used by Hack than the one proposed here. It > makes a lot more sense to me intuitively, probably because the property > declarations still looks like normal property declarations, they just occur > in-line in the ctor. > > Nikita >
To add to this: While I can totally understand the motivation to avoid the property/constructor boilerplate (where the property name needs to be repeated four times), I think that this is really solving the wrong problem. The problem is the need to have a constructor at all. Both this RFC and the two alternatives mentioned above really target the case of "dumb" constructors that don't really do anything beyond assigning properties from ctor arguments. I think that that is better solved by adding a first-class syntax for object construction. I have something roughly like this in mind: class Point { public int $x; public int $y; public int $z; } // (syntax just a dummy) $origin = new Point { x = 0, y = 0, z = 0 }; Where the object initialization syntax ensures that all properties that don't have defaults are initialized. Especially now that we have typed properties and it is feasible to have data objects with just public typed properties, I think that this is the way to avoid ctor boilerplate, rather than making it simpler to write that boilerplate. Nikita

Rowan Collins

7 years ago
On Fri, 25 Jan 2019 at 11:05, Nikita Popov <nikita.ppv@gmail.com> wrote:
> class Point { > public int $x; > public int $y; > public int $z; > } > > // (syntax just a dummy) > $origin = new Point { x = 0, y = 0, z = 0 }; > > Where the object initialization syntax ensures that all properties that > don't have defaults are initialized. Especially now that we have typed > properties and it is feasible to have data objects with just public typed > properties, I think that this is the way to avoid ctor boilerplate, rather > than making it simpler to write that boilerplate. >
The big difference here is that you are making the short-hand the responsibility of the caller, rather than the definer. I suspect there's a Venn diagram of use cases where the two features would be useful. In particular, the call-site syntax you have there would work really well for a value type, and could go with having full support for that (e.g. have the resulting object be immutable / copy-on-write); it works less well for something like dependency injection, where the properties would normally be private, and you might want to combine the short-hand with some normal constructor logic. Regards,
-- Rowan Collins [IMSoP]

Levi Morrison

7 years ago
On Fri, Jan 25, 2019 at 4:05 AM Nikita Popov <nikita.ppv@gmail.com> wrote:
> > On Fri, Jan 25, 2019 at 11:44 AM Nikita Popov <nikita.ppv@gmail.com> wrote: > > > On Wed, Jan 23, 2019 at 1:33 PM Andrey O Gromov <AGromov@alfabank.ru> > > wrote: > > > >> Full description > >> https://wiki.php.net/rfc/code_free_constructor > >> Draft realisation > >> https://github.com/php/php-src/compare/master...rjhdby:constructor > >> > >> "Code free" constructor is constructor with only purpose to directly set > >> object properties from received parameters and, optionally, call parent > >> constructor. > >> > >> Main idea is to move such constructor declaration inside class > >> declaration. > >> > >> Simple example: > >> > >> Current syntax > >> class A extends B{ > >> public $prop; > >> > >> public function __construct($prop){ > >> parent::__construct("BlaBla", $prop); > >> $this->prop = $prop; > >> } > >> } > >> > >> Proposed syntax > >> class A($prop) extends B("BlaBla", $prop) { > >> } > >> > >> With respect, Andrey. > > > > > > Two alternatives you might want to consider: > > > > * https://wiki.php.net/rfc/automatic_property_initialization => Proposed > > function public function __construct(int $this->x, int $this->y) {}, which > > avoids the need for explicit property assignments in the ctor. However, the > > property still needs to be declared separately. > > > > * > > https://docs.hhvm.com/hack/other-features/constructor-parameter-promotion > > => Uses public function __construct(public int $x, public int $y) {} to > > declare properties in-line in the constructor. > > > > I think that *if* we want to add some kind of sugar of this type, then I'd > > strongly prefer the syntax used by Hack than the one proposed here. It > > makes a lot more sense to me intuitively, probably because the property > > declarations still looks like normal property declarations, they just occur > > in-line in the ctor. > > > > Nikita > > > > To add to this: While I can totally understand the motivation to avoid the > property/constructor boilerplate (where the property name needs to be > repeated four times), I think that this is really solving the wrong > problem. The problem is the need to have a constructor at all. > > Both this RFC and the two alternatives mentioned above really target the > case of "dumb" constructors that don't really do anything beyond assigning > properties from ctor arguments. I think that that is better solved by > adding a first-class syntax for object construction. I have something > roughly like this in mind: > > class Point { > public int $x; > public int $y; > public int $z; > } > > // (syntax just a dummy) > $origin = new Point { x = 0, y = 0, z = 0 }; > > Where the object initialization syntax ensures that all properties that > don't have defaults are initialized. Especially now that we have typed > properties and it is feasible to have data objects with just public typed > properties, I think that this is the way to avoid ctor boilerplate, rather > than making it simpler to write that boilerplate. > > Nikita
I support this idea, although I think the `=` should be `=>` like arrays, or `:` like JSON. If you have any more complex of a need (such as private variables) then I think you should write the constructor. The reason is that if you have private variables, you need to establish a public API contract.

Rowan Collins

7 years ago
On Fri, 25 Jan 2019 at 15:37, Levi Morrison <levim@php.net> wrote:
> > If you have any more complex of a need (such as private variables) > then I think you should write the constructor. The reason is that if > you have private variables, you need to establish a public API > contract. >
Right, which is why I think this is solving a different problem. The OP was proposing a syntax that would allow you to simplify cases like "call parent constructor with this constant, then set these 3 properties"; a call-time syntax like this is no use for that. Regards,
-- Rowan Collins [IMSoP]

Andrey O Gromov

7 years ago
Just updated proposal https://wiki.php.net/rfc/code_free_constructor v 0.2 Added visibility modificators syntax. Changed behavior for parameters that need to be forwarded to parent. Added “anonymous class” section. Added “Q&A, Discussion” section. Improved description of realization.

Sebastian Bergmann

7 years ago
Am 25.01.2019 um 11:44 schrieb Nikita Popov:
> I think that *if* we want to add some kind of sugar of this type, then I'd > strongly prefer the syntax used by Hack than the one proposed here.
Agreed.