Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:112105 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 30515 invoked from network); 23 Oct 2020 15:50:26 -0000 Received: from unknown (HELO localhost.localdomain) (76.75.200.58) by pb1.pair.com with SMTP; 23 Oct 2020 15:50:26 -0000 To: internals@lists.php.net References: Date: Fri, 23 Oct 2020 17:08:05 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-Posted-By: 79.207.25.186 Subject: Re: Is there any interest for object constructor shorthand *just forstdClass* From: php@philiagus.de (Andreas Bittner) Message-ID: > e.g. `$x = object{key: object{'escaped-literal': $v2 }};` > (equivalent to `$x = (object)['key' => (object)['escaped-literal' => $v2]];`) > > For example, in JS, non-string key literals are surrounded in `[]` to unambiguously reference them. > Here, that could be `object{[$key]: $value, [MY_CONST]: $other}` - but `(MY_CONST)` would also work > > - https://externals.io/message/52990 was mentioned 9 years ago but would potentially conflict with future block expression RFCs > - `object{key: $value}` is suggested here for similarity to named arguments > > Benefits: > - Shorter and more readable code - casting an array to an object is an unintuitive and potentially hard to remember > way to create an object literal > - Make it easier for users to use objects for generic associative data instead of using arrays both for lists and associative data, > in situations where it may result in more usable APIs > > For example, > > ``` > $x = new stdClass{}; > $x->prop = new stdClass{}; > $x->prop->a = $a; > $x->prop->b = $b; > // Could be shortened to > $x = object{prop: object{a: $a, b: $b}} > // $x = (object)['prop' => (object)['a' => $a, 'b' => $b]] > ``` Creating a new syntax, that is only used in context of \stdClass, feels like overkill. Unfortunately, I cannot come up with a use case for this syntax, outside of the \stdClass context. I would also debate the point of the new syntax being more readable compared to the `(object)` cast, but that very much depends on what the reader is used to. I would however like to point out that shorter isn't always better and sometimes more verbose code is easier to understand. Imho a language shouldn't look like code-golf by recommendation. But I don't want to and hope I didn't sidetrack the discussion. With regards to the matter at hand I can see where you are coming from. `(object)['prop' => 1, ...]` feels very indirect, needlessly creating an array instance just to get an object out of it. Wouldn't it be opportune to just use named arguments? ``` $x = new \stdClass( prop: new \stdClass( a: $a, b: $b ) ); ``` While this isn't as short as the object{} suggestion, it doesn't add any additional language constructs. The signature of \stdClass constructor would change to `\stdClass(...$defaultProperties)`. Maybe this is the kickoff for variadic property promotion `__constructor(public mixed ...$properties)`. The following would be true: `new \stdClass(1, 2, 3, prop: 1.2) == (object)[1, 2, 3, 'prop' => 1.2];` On the subject of dynamic/variable property names: I would suggest that a RFC for the syntax `functionA($parameterName: 'value')` should be submitted at some point. This would replace the already working `functionA(...[$parameterName => 'value'])`. Maybe we even find a way of using constants as well, which would could be something like your suggested `functionA([SOME_CONST]: 'value')`. This would allow everyone to benefit from the change, not only \stdClass. Closing I would like to make a short point with regards to the `(object)` cast: Both a cast of \stdClass to `(array)` and a cast of arrays to `(object)` are common use cases in (JSON-)API development. It is not unheard of for API signatures to contain certain properties of the JSON response object only if some conditions are met. Currently the best way to achieve this is either by dynamically adding properties to an existing \stdClass object, or by populating an array and `(object)` casting it later. - Andreas