Proposal: Shorthand initialization and destructuring of associative arrays

php.internals

Konrad Baumgart

4 years ago
Hi everyone, I'd like to propose 2 syntactic sugars: $array = [ => $data]; // the same as $array = ['data' => $data] and [ => $data] = $array; // the same as ['data' => $data] = $array My biggest use-case for this would be conveniently returning multiple things from a function, like: function getDataForDashboard() { … return [ => $dailyAggregations, => $weeklyAggregations]; } [ => $dailyAggregations, => $weeklyAggregations] = getDataForDashboard(); Similar effects can be achieved with compact()/extract() functions, but I dislike those functions because they make it hard to find usages of variables. Using numerical arrays instead makes the code less readable and more error-prone for me. Using ['dailyAggregations' => $dailyAggregations,…] would force you to split code into multiple lines and negatively affect readability. I was recently developing with js/ts and I liked the ease of returning multiple items from a function as an object, while still preserving their name. I have spare time this October, so I would happily get into php interpreter by developing this. I'm looking forward for your feedback, Konrad Baumgart

Lynn

4 years ago
On Mon, Sep 27, 2021 at 11:27 AM Konrad Baumgart <konrad@baumgart.pl> wrote:
> I was recently developing with js/ts and I liked the ease of returning > multiple items from a function as an object, while still preserving > their name. >
I recently encountered this as well in Typescript. I believe the syntax is something like this? ```js const someProperty = "something"; const foo = { someProperty, anotherProperty: "Something else", }; // same as const foo = { someProperty: someProperty, anotherProperty: "Something else", }; ``` Obviously this won't work with PHP arrays, which is probably why you decided for `=> $someProperty`. I'm a big no-no when it comes to `compact()` and `extract()`. These functions make my life hell. Despite knowing what they do, it still takes me a lot of reading to try and figure out what they do. Even now I will have to go to the documentation to understand exactly how either of them work. Renaming a variable in a certain scope should not break something outside of that scope, and I see this as a big problem in the proposal. When I take your example, spot the error that will cause everything to break runtime with limited static analysis to let you know (hint: missing a g in the first variable). ```php return [ => $dailyAgregations, => $weeklyAggregations]; ``` Refactoring tools could just ignore the outside scope and automatically change it, yet this won't solve anything for text find and replace. ```php return [ 'dailyAggregations' => $theNewVariableName, => $weeklyAggregations, ]; ``` If something like this were to be introduced, I'd happily see it happen with anonymous objects and interfaces accepting properties: ```php interface DashboardAggregations { public readonly array $dailyAggregations; public readonly array $weeklyAggregations; } function getDashboardData() : DashboardAggregations { $dailyAggregations = []; $weeklyAggregations = []; // ... return { $dailyAggregations, $weeklyAggregations, }; // same as return { dailyAggregations: $dailyAggregations, weeklyAggregations: $weeklyAggregations, }; // same as (if properties in interfaces were allowed) return new class($dailyAggregations, $weeklyAggregations) implements DashboardAggregations { public function __construct( public readonly array $dailyAggregations, public readonly array $weeklyAggregations, ) {} }; } ``` If you then really need the destructuring, you could do something like this (just a random syntax chosen), though I'd still be in favor of leaving this aside as you now have a nice object with properties that are accessible. ```php {$dailyAggregations, $weeklyAggregations} = getDashboardData(); ``` This way php could verify the return value with the return type, and static analyzers can determine the structure of what's to be returned. Imo this functionality is not worth the headache with arrays. That said, it feels like this proposal is more of a tuple/multiple return.

Konrad Baumgart

4 years ago
> I have spare time this October, so I would happily get into php interpreter by developing this.
Unfortunately my plans to have spare time FAILED and I'm not able to contribute in the near future.
> If something like this were to be introduced, I'd happily see it happen with anonymous objects and interfaces accepting properties:
Using classes/interfaces rather than associative arrays is superior in 'enterprise' projects, but sometimes I just want to quickly return tuple or construct json response.
> This way php could verify the return value with the return type, and static analyzers can determine the structure of what's to be returned. Imo this functionality is not worth the headache with arrays.
We recently got #[ArrayShape]. Maybe associative arrays will get more love from static analyzers and will be suitable for 'tuple returns'.

Sara Golemon

4 years ago
On Mon, Oct 4, 2021 at 2:15 PM Konrad Baumgart <konrad@baumgart.pl> wrote:
> > I have spare time this October, so I would happily get into php > interpreter by developing this. > Unfortunately my plans to have spare time FAILED and I'm not able to > contribute in the near future. > >
I'm procrastinating writing slides for Longhorn, so here's a quick and dirty implementation to work with: https://github.com/sgolemon/php-src/commit/4156d9d989314b2d60d1031ab9e02faaefa248f9 Not actually sure it's got value, but you shouldn't be held back from proposing it by a lack of implementation. -Sara

Nikita Popov

4 years ago
On Mon, Sep 27, 2021 at 11:27 AM Konrad Baumgart <konrad@baumgart.pl> wrote:
> Hi everyone, > > I'd like to propose 2 syntactic sugars: > $array = [ => $data]; // the same as $array = ['data' => $data] > and > [ => $data] = $array; // the same as ['data' => $data] = $array > > My biggest use-case for this would be conveniently returning multiple > things from a function, like: > > function getDataForDashboard() { > … > return [ => $dailyAggregations, => $weeklyAggregations]; > } > > [ => $dailyAggregations, => $weeklyAggregations] = getDataForDashboard(); > > Similar effects can be achieved with compact()/extract() functions, > but I dislike those functions because they make it hard to find usages > of variables. Using numerical arrays instead makes the code less > readable and more error-prone for me. Using ['dailyAggregations' => > $dailyAggregations,…] would force you to split code into multiple > lines and negatively affect readability. > > I was recently developing with js/ts and I liked the ease of returning > multiple items from a function as an object, while still preserving > their name. > > I have spare time this October, so I would happily get into php > interpreter by developing this. > > I'm looking forward for your feedback, > Konrad Baumgart >
I'm generally in favor of this functionality. Unfortunately the syntax options we have for this are not as nice as in other languages. [=> $x] is probably the most reasonable choice where array literals are concerned. https://wiki.php.net/rfc/named_params#shorthand_syntax_for_matching_parameter_and_variable_name also has some thoughts on this topic, as named params have the same problem. Regards, Nikita