Re: [PHP-DEV] [RFC] Object Initializer

This is only part of a thread. view whole thread
  107041
September 13, 2019 05:49 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
Hi Lynn,

czw., 12 wrz 2019 o 17:01 Lynn <kjarli@gmail.com> napisał(a):

> Heya, > > What's the added benefit of this compared to implementing a constructor? > > The part I like is that this can be used to replace stdClass/structured > arrays. Perhaps something like this would nice to have in PHP: > > ``` > $people = []; > > foreach ($peopleFromDatabase as [$id, $username, $name]) { > $people[] = { > Uuid id => $id, > string username => $username, > string name => $name, > }; > // and possible automatic assignment: > $people[] = {Uuid $id, string $username, string $name}; > } > ``` >
Removing stdClass for instantiation and initialization of simple objects is one of a future scope proposal. This RFC tries to address instantiation and initialization boilerplate reduction with a syntax which would not be restricted to stdClass only. Although it's not a game-changer, simple addition to the language which reduces boilerplate when dealing with objects which don't need complex constructors like for eg. DTO objects.. Regards,
> Lynn van der Berg > >
Regards, Michał Brzuchalski
  107043
September 13, 2019 06:39 claude.pache@gmail.com (Claude Pache)
> Le 13 sept. 2019 à 07:49, Michał Brzuchalski brzuchalski@gmail.com> a écrit : > > Hi Lynn, > > czw., 12 wrz 2019 o 17:01 Lynn <kjarli@gmail.com <mailto:kjarli@gmail.com>> napisał(a): > >> Heya, >> >> What's the added benefit of this compared to implementing a constructor? >> >> The part I like is that this can be used to replace stdClass/structured >> arrays. Perhaps something like this would nice to have in PHP: >> >> ``` >> $people = []; >> >> foreach ($peopleFromDatabase as [$id, $username, $name]) { >> $people[] = { >> Uuid id => $id, >> string username => $username, >> string name => $name, >> }; >> // and possible automatic assignment: >> $people[] = {Uuid $id, string $username, string $name}; >> } >> ``` >> > > Removing stdClass for instantiation and initialization of simple objects is > one of a future scope proposal. > > This RFC tries to address instantiation and initialization boilerplate > reduction with a syntax which would > not be restricted to stdClass only. > > Although it's not a game-changer, simple addition to the language which > reduces boilerplate when dealing > with objects which don't need complex constructors like for eg. DTO objects. >
As for `stdClass`, PHP has already a syntax: $baz = "baz"; $obj = (object) [ "foo" => "bar", $baz => true ]; For other type of objects, that could be done with a simple helper function $customer = object_assign(new Customer, [ "id" => 123, "name" => "John Doe", ]); where: function object_assign(object $obj, iterable $data): object { foreach ($data as $key => $value) { $obj->$key = $value; } return $obj; } That said, I generally use arrays rather than DTO objects or such, so that I can’t speak from experience. —Claude
  107045
September 13, 2019 07:15 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
Hi Claude,

pt., 13 wrz 2019 o 08:39 Claude Pache pache@gmail.com> napisał(a):

> > > Le 13 sept. 2019 à 07:49, Michał Brzuchalski brzuchalski@gmail.com> > a écrit : > > Hi Lynn, > > czw., 12 wrz 2019 o 17:01 Lynn <kjarli@gmail.com> napisał(a): > > Heya, > > What's the added benefit of this compared to implementing a constructor? > > The part I like is that this can be used to replace stdClass/structured > arrays. Perhaps something like this would nice to have in PHP: > > ``` > $people = []; > > foreach ($peopleFromDatabase as [$id, $username, $name]) { > $people[] = { > Uuid id => $id, > string username => $username, > string name => $name, > }; > // and possible automatic assignment: > $people[] = {Uuid $id, string $username, string $name}; > } > ``` > > > Removing stdClass for instantiation and initialization of simple objects is > one of a future scope proposal. > > This RFC tries to address instantiation and initialization boilerplate > reduction with a syntax which would > not be restricted to stdClass only. > > Although it's not a game-changer, simple addition to the language which > reduces boilerplate when dealing > with objects which don't need complex constructors like for eg. DTO > objects. > > > As for `stdClass`, PHP has already a syntax: > > $baz = "baz"; > $obj = (object) [ > "foo" => "bar", > $baz => true > ]; > > For other type of objects, that could be done with a simple helper function > > $customer = object_assign(new Customer, [ > "id" => 123, > "name" => "John Doe", > ]); > > where: > > function object_assign(object $obj, iterable $data): object { > foreach ($data as $key => $value) { > $obj->$key = $value; > } > return $obj; > } > > That said, I generally use arrays rather than DTO objects or such, so that > I can’t speak from experience. > > —Claude > > You're of course right this can be done more or less with a helper function
which does all the required type validation through reflection, but I believe that feature requests for language support which reduces boilerplate can easily spread that simplification and bring all the required type check validations out of the box, right? IMO the thing is as you said this would require a helper function and not all simply like them! Regards, Michał Brzuchalski
  107047
September 13, 2019 07:35 mike@newclarity.net (Mike Schinkel)
> That said, I generally use arrays rather than DTO objects
I too have often used arrays. But then I have always been rigorous to ensure that variables and array elements are initialized before use, and fortunately I do not have a lot of typos in code I write. However I recently took on a large PHP app to refactor where the previous developers had used arrays profusely with very little pre-initialization. So I started to add in all initialization and checking to be certain variables had been initialized and realized it was an overwhelming task. I changed course and am now replacing all all arrays that are emulating a struct (vs a collection) to instances of declared classes and it has made a major improvement in my ability to refactor without bloating the code to 2-3x the original size. I has also allowed me to consolidate lots of repeated code in one place in methods and constructors. Given that experience and knowing that using "args" for optional parameters means my function signatures are much less likely to change, it would be super helpful if I could do so with type-checked object initializers instead of array literals. -Mike
  107059
September 13, 2019 08:51 arnold.adaniels.nl@gmail.com (Arnold Daniels)
This can easily be done in a number of ways, like the suggested helper
function. The same can be said for many other features that were
implemented recently, like array unpacking. This feature is easy to
implement and will make the code for data objects much more readable, with
additional benefits for static analysis.

Comments:

I don't like how it works for anonymous classes. It's more difficult to
implement since the compiler doesn't know the meaning of the (first)
bracket. It's doesn't make the code more readable, for the same reason. I
think it's better to not support this syntax with anonymous classes.

The examples do not show how constructor arguments are passed. I'm assuming
it's

    $customer = new Customer("foo") {
        name = "John"
    };

About the idea of letting `{ foo = 10 }` create an `stdClass` object (not
in the RFC); While not used much since it has no effect, it's perfectly
okay to put your code in brackets eg `{ { { $foo = 10; } } }`. As such, I
don't think it's a good idea to allow `new stdClass` to be omitted.
  107063
September 13, 2019 09:04 mike@newclarity.net (Mike Schinkel)
Arnold,

> This can easily be done in a number of ways, like the suggested helper > function.
A helper function can simulate an object initializer but it cannot provide the same potential benefits. The helper function uses array keys to identify properties, and as array keys cannot be declared like class properties, neither IDE, tools, nor PHP itself can validate the names and types of those keys like they could if object initializers were used instead. Michal,
> I don't like how it works for anonymous classes. It's more difficult to > implement since the compiler doesn't know the meaning of the (first) > bracket. It's doesn't make the code more readable, for the same reason. I > think it's better to not support this syntax with anonymous classes. > > The examples do not show how constructor arguments are passed. I'm assuming > it's > > $customer = new Customer("foo") { > name = "John" > }; > > About the idea of letting `{ foo = 10 }` create an `stdClass` object (not > in the RFC); While not used much since it has no effect, it's perfectly > okay to put your code in brackets eg `{ { { $foo = 10; } } }`. As such, I > don't think it's a good idea to allow `new stdClass` to be omitted.
I am curious why your RFC uses "=" instead of "=>" for separating properties from values? If we used "=>" it is potential — with lookahead parsing — that the following could be unambiguous: { foo => 10 } -Mike
  107067
September 13, 2019 09:22 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
Hi Mike,

I am curious why your RFC uses "=" instead of "=>" for separating
> properties from values? > > If we used "=>" it is potential — with lookahead parsing — that the > following could be unambiguous: > > { foo => 10 } > > The reason about choosing "=" was a simplification of instantiation and
properties initialisation and we use "=" to assign property values now. The "=>" is specific for array key pairs and IMO should stay specific for arrays only. Thanks, Michał Brzuchalski
  107068
September 13, 2019 09:29 mike@newclarity.net (Mike Schinkel)
> IMO should stay specific for arrays only.
Why? Is there an objective reason? Is there some aspect of the syntax that makes it appropriate for arrays but inappropriate for object initialization? These are honest question. My two cents: I would like to type less too, but I have always assumed that "=>" was the PHP-ish syntax for initialization of a structure so it seems very appropriate to use for object initialization too. That said, 1. I don't feel strongly about iti either way, 2. Unless using "=>" would make naked object initialization possible — i.e. { foo => 10 } — given that it seems, as Arnold said, this would conflict with other meanings: { foo = 10 } #fwiw -Mike
  107070
September 13, 2019 09:39 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
pt., 13 wrz 2019 o 11:29 Mike Schinkel <mike@newclarity.net> napisał(a):

> IMO should stay specific for arrays only. > > > Why? Is there an objective reason? > > $obj->foo => 123;
Simply, that's not the way you initialize object property values. When you use "=>" in array context you're pushing a new value to array and it'll work without labelling it with key where the key could be number index or string index in what shape you want (whitespaces etc.).
> Is there some aspect of the syntax that makes it appropriate for arrays > but inappropriate for object initialization? > > > These are honest question. > > > My two cents: I would like to type less too, but I have always assumed > that "=>" was the PHP-ish syntax for initialization of a structure so it > seems very appropriate to use for object initialization too. > > > That said, > > > 1. I don't feel strongly about iti either way, > > 2. Unless using "=>" would make naked object initialization possible — > i.e. { foo => 10 } — given that it seems, as Arnold said, this would > conflict with other meanings: { foo = 10 } > > > { $foo = 123 }; // unexpected "}" cause of missing ";"
$bar = { $foo = 123 }; // unexpected "{" cause it's not allowed in this context Both examples are syntax error. You can use {} for separating blocks of code, but now if you wanna assign value. Everything considered syntax error can be used for feature shaping. Regards, Michał Brzuchalski
  107072
September 13, 2019 09:47 mike@newclarity.net (Mike Schinkel)
> On Sep 13, 2019, at 2:39 AM, Michał Brzuchalski brzuchalski@gmail.com> wrote: > $obj->foo => 123; > Simply, that's not the way you initialize object property values.
So by the same logic this should be PHP's way to initialize array elements, right? $arr['foo'] => 123; But it is not. Obviously we both know that this is the correct syntax: $arr['foo'] = 123; So that is why I think it would be more consistent in PHP for object initializers to use "=>" instead of "=." But, I myself will not belabor the point beyond this message. Either others will agree with you or they will suggest to change to "=>" too.
> { $foo = 123 }; // unexpected "}" cause of missing ";" > $bar = { $foo = 123 }; // unexpected "{" cause it's not allowed in this context > Both examples are syntax error. > You can use {} for separating blocks of code, but now if you wanna assign value. > Everything considered syntax error can be used for feature shaping.
Hmm. Ok, I will let Arnold reply to you on this if he feels that your reply did not address his concerns. -Mike
  107065
September 13, 2019 09:19 michal@brzuchalski.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
Hi Arnold,

pt., 13 wrz 2019 o 10:51 Arnold Daniels nl@gmail.com>
napisał(a):

> This can easily be done in a number of ways, like the suggested helper > function. The same can be said for many other features that were > implemented recently, like array unpacking. This feature is easy to > implement and will make the code for data objects much more readable, with > additional benefits for static analysis. > > Comments: > > I don't like how it works for anonymous classes. It's more difficult to > implement since the compiler doesn't know the meaning of the (first) > bracket. It's doesn't make the code more readable, for the same reason. I > think it's better to not support this syntax with anonymous classes. > > Probably lexical scope for anon classes would be better here, but due to
fact that proposal is to use initializer block instead of constructor arguments, that was the reason why initializer block got before anon class definitions.
> The examples do not show how constructor arguments are passed. I'm assuming > it's > > $customer = new Customer("foo") { > name = "John" > }; > > The examples don't show that cause it's forbidden.
There is a note on that in RFC on purpose
> Note! Object instantiation allows only constructors without required arguments to be used.
> Any class which requires passing arguments to constructor cannot be used in combination with object initializer.
Using constructor arguments and object initializer would introduce noise and you'll be potentially initializing object twice: using object initializer block and using constructor args what may be misleading.
> About the idea of letting `{ foo = 10 }` create an `stdClass` object (not > in the RFC); While not used much since it has no effect, it's perfectly > okay to put your code in brackets eg `{ { { $foo = 10; } } }`. As such, I > don't think it's a good idea to allow `new stdClass` to be omitted. >
Future scope mentions only about letting to create stdClass with omitting of the class name only, nothing said about removing a new keyword. Thanks, Michał Brzuchalski
  107075
September 13, 2019 11:26 kjarli@gmail.com (Lynn)
On Fri, Sep 13, 2019 at 10:51 AM Arnold Daniels <
arnold.adaniels.nl@gmail.com> wrote:

> Comments: > > I don't like how it works for anonymous classes. It's more difficult to > implement since the compiler doesn't know the meaning of the (first) > bracket. It's doesn't make the code more readable, for the same reason. I > think it's better to not support this syntax with anonymous classes. > > The examples do not show how constructor arguments are passed. I'm assuming > it's > > $customer = new Customer("foo") { > name = "John" > }; > > About the idea of letting `{ foo = 10 }` create an `stdClass` object (not > in the RFC); While not used much since it has no effect, it's perfectly > okay to put your code in brackets eg `{ { { $foo = 10; } } }`. As such, I > don't think it's a good idea to allow `new stdClass` to be omitted. >
If the compiler implementation of `$foo = {...};` would give issues, `$foo = new {...};` could be an alternative for run-time declared anonymous classes (preferably with typed properties). In regards of stdClass, I don't think this should be used. Regards, Lynn van der Berg