Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:109181 Return-Path: Delivered-To: mailing list internals@lists.php.net Received: (qmail 78130 invoked from network); 21 Mar 2020 20:07:25 -0000 Received: from unknown (HELO localhost.localdomain) (76.75.200.58) by pb1.pair.com with SMTP; 21 Mar 2020 20:07:25 -0000 To: internals@lists.php.net References: Date: Sat, 21 Mar 2020 19:31:09 +0100 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:52.0) Gecko/20100101 Firefox/52.0 SeaMonkey/2.49.2 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Posted-By: 46.59.72.204 Subject: Re: [PHP-DEV] [RFC] [DISCUSSION] Compact Object Property Assignment From: ajf@ajf.me (Andrea Faulds) Message-ID: Hi, Jakob Givoni wrote: > Hello Internals, > > I'm opening up my new RFC for discussion: > > https://wiki.php.net/rfc/compact-object-property-assignment > - A pragmatic approach to object literals > > Let me know what you think! > > Best, > Jakob > I really don't like this `(new Foo)->[]` syntax for a few reasons: * It doesn't seem unreasonable to me to imagine that `->` could be overloaded to take a value that isn't a string for the property name. Of course, that would be `(new Foo)->{[]}` not `(new Foo)->[]`, but it is too close for comfort for me. * It looks like short array syntax, but it's not an array, in fact it is an object, which is a similar but different thing. * Brackets normally enclose an expression: if I have `new Foo`, I can enclose that as `(new Foo)`, yet this is adding something extra to the `new` expression while not being part of it? This is surprising to me. If it affects the `new`, it should be inside the brackets. * Do we need the brackets? I think there are some alternative syntaxes that could be used as inspiration. C99 has a versatile feature called “designated initialisers”, which lets you initialise not only structs but arrays: // Struct initialisation struct some_struct foo = { .bar = 1, .baz = 2, }; // Array initialisation int bar[] = { [0] = 1, [1] = 2, }; Notice how the syntax between the curly braces resemblance the normal syntax for accessing and assigning to members of a type. A normal struct member assignment on its own looks like `foo.bar = 1;`, so within the curly braces you write `.bar = 1,`. Likewise a normal array member assignment on its own looks like `bar[0] = 1;`, so within the curly braces you write `[0] = 1,`. This resemblance provides familiarity for someone seeing the syntax for the first time and provides a clue as to what it does, and also retains the visual distinctiveness between array and struct assignments. If we were to copy the C99 model, perhaps it would look something like: $foo = new Foo { ->bar = 1, ->baz = 2, }; (I am assuming the call to the constructor has no arguments here, but otherwise you would insert the normal argument list brackets before the opening `{`. I have used `{` here like C, but perhaps `[` would be better. There would also be the question of whether `=` should be `=>` if we want to deliberately resemble arrays.) However, we don't have to be so imaginitive and adapt a similar feature, because C# already has the exact feature you are proposing, and calls it “object initialisers”: Foo foo = new Foo { bar = 1, baz = 2, }; (I am again assuming the call to the constructor has no arguments. If there are arguments, they go before the opening `{` in C#.) I am neutral on whether it's a better or worse syntax than using `->`. Side-note, C# even supports a special kind of anonymous classes with “object initialisers”: var foo = new { bar = 1, baz = 2, }; I think PHP won't need this given `new stdClass {` would work perfectly well, although it would be nice to have a shorter and prettier alternative to the current `(object)[`. Anyway, thanks for proposing something I have wanted for ages but never gotten round to implementing. :) Andrea