Re: [PHP-DEV] [RFC] [DISCUSSION] Compact Object Property Assignment

This is only part of a thread. view whole thread
  109201
March 22, 2020 03:09 jakob@givoni.dk (Jakob Givoni)
I just realized that syntax C and D as proposed - without anything to
signify end of COPA - become really awkward when writing nested COPA:

$foo->
    a = 1,
    b = 2,
    c = (new Foo)->
        a = 3,
        b = 4,.
    ,
;

How do we indicate that the nested block ends and jump back to the outer one?

On Sat, Mar 21, 2020 at 9:47 PM Jakob Givoni <jakob@givoni.dk> wrote:
> > Hi Andrea, thanks for your feedback. > Let's talk about syntax then :-) > > The currently suggested syntax is > > -> [ > = , > ... > ] > > The 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 <ajf@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 > >