Hi Andrea, thanks for your feedback. Let's talk about syntax then :-) The currently suggested syntax is
<object-expression> -> [ <property-name> = <expression>, ... ] The <object-expression> can be an existing object: $foo->[a = 1]; Or a new, yet anonymous, object: (new Foo)->[a = 1]; 1. The (normal) brackets =================== The reason I think it's necessary to wrap the new Foo in brackets is because it's a language construct and not an expression in itself. Wrapping it in brackets make it an expression. For example, these are both syntax errors (missing brackets): new Foo->a = 1; new Foo()->setA(1); In this RFC I did not want to propose changing the lexer/parser to make that possible, since my focus was to suggest a rather trivial implementation. I'm open to change this view, but only if someone with solid knowledge of internals come forward and promise that it's a good idea. 2. The arrow ========== When the arrow follows an object expression it suggest we're doing something on that object, like accessing a property (set/get) or calling a method. There are exceptions though: When the object expression is followed by curly or square brackets it means we're accessing it as if it were an array: $foo[1] $foo{1} // Deprecated And when it's followed by normal brackets, we're invoking it as a callable: $foo() I see a window of opportunity here though: Since the curly brackets were deprecated in PHP 7.4 we could repurpose it for COPA: $foo{a = 1, b = 2} Is it too soon? 3. The square brackets ================== The assignments need to be grouped together, somehow (at least I think that's the sane thing to do?) - we cannot use curly brackets as, like you say, that's reserved to create an expression that evaluates to a property name: $foo->{a =1, b = 2}; // syntax error, unexpected '=' That leaves us with either normal brackets or square brackets: $foo->(a = 1, b = 2); $foo->[a = 1, b = 2]; Which one is more natural when we're dealing with structure data? 4. The property name ================ All I can say is that I really don't want to add anything that is not strictly necessary, like the arrow before each property, unless it's adding something of actual value. Familiarity you say... yes, I can see that, but it gets very verbose with that leading arrow... In my opinion array literal syntax is already too verbose for me. 5. The equals sign ============== I don't really know why => was chosen for array assignment, since we use simple = to assign values everywhere else. Since i prefer it less verbose, and since we already use = in $foo->a = 1 I think a single = is the best option. COPA is NOT object initializer ======================= COPA can follow any object expression and has nothing to do with object construction in itself. You can use COPA as many times as you like at any point in an object's life. Though object initializer would also solve what COPA is solving, COPA doesn't introduce any new concepts, just new syntax. I don't know why object initializer and other similar proposals failed in the past, but I wanted to try something different, less elaborate and more pragmatic. I don't know if COPA has any better chance than those that came before :-) I am going to suggest a few alternative syntaxes that we can also vote on, but only after they've been vetted by experienced internals developers. Syntax A - the initial one Syntax B: $foo{ a = 1, b = 2, }; Syntax C: $foo->a = 1, b = 2; Syntax D: $foo->a = 1, ->b = 2; Syntax E: $foo->( a = 1, b = 2, ); We can try to iterate over these as well, please let me know what you think! On Sat, Mar 21, 2020 at 1:31 PM Andrea Faulds <a...@ajf.me> wrote: > > 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 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php