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

  109055
March 16, 2020 11:48 jakob@givoni.dk (Jakob Givoni)
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
  109058
March 16, 2020 14:10 matthewmatthew@gmail.com (Matthew Brown)
I love the idea!

The syntax for new objects looks a little verbose – would it be possible to
use

$foo = new Foo()[
  property1 = "hello",
  property2 = 5,
];

as an alternative to

$foo = (new Foo())->[
  property1 = "hello",
  property2 = 5,
];


On Mon, 16 Mar 2020 at 07:48, Jakob Givoni <jakob@givoni.dk> 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 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  109078
March 16, 2020 18:40 mike@newclarity.net (Mike Schinkel)
For reference:

https://wiki.php.net/rfc/object-initializer
https://externals.io/message/106947

That was quite the discussion, and it started only 6 months ago.

-Mike 


> On Mar 16, 2020, at 10:10 AM, Matthew Brown <matthewmatthew@gmail.com> wrote: > > I love the idea! > > The syntax for new objects looks a little verbose – would it be possible to > use > > $foo = new Foo()[ > property1 = "hello", > property2 = 5, > ]; > > as an alternative to > > $foo = (new Foo())->[ > property1 = "hello", > property2 = 5, > ]; > > > On Mon, 16 Mar 2020 at 07:48, Jakob Givoni <jakob@givoni.dk> 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 >> >> -- >> PHP Internals - PHP Runtime Development Mailing List >> To unsubscribe, visit: http://www.php.net/unsub.php >> >>
  109083
March 17, 2020 01:13 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 9:10 AM Matthew Brown <matthewmatthew@gmail.com> wrote:
> I love the idea! Thanks Matthew!
> The syntax for new objects looks a little verbose – would it be possible to use > > $foo = new Foo()[ > property1 = "hello", > property2 = 5, > ]; The short answer: I don't think so.
This is not possible (though it's arguably 'nicer'): new Foo()->doSomething(); // syntax error, unexpected '->' Not sure why, but it's necessary to wrap the instantiation in brackets: (new Foo())->doSomething(); // Ok If someone can explain why, it would be enlightening! Furthermore, dropping the arrow would create conflicting syntax with array access: $foo[1]; // Array access, give me the element with index 1, can be used on objects as well $foo[a = 1]; // Property assignment... ??? I'll update the RFC to reflect your proposal. Thank you, Jakob
  109115
March 17, 2020 21:33 matthewmatthew@gmail.com (Matthew Brown)
I don't think it's conflicting _if you insist on brackets_ after the new
expression. PHP Parser grammar for "new" expressions is

T_NEW class_name_reference ctor_arguments

If you allowed the shorter syntax, ctor_arguments would allow an
object_properties entry.

I'm sure Nikita could clarify, though.


On Mon, 16 Mar 2020 at 21:13, Jakob Givoni <jakob@givoni.dk> wrote:

> On Mon, Mar 16, 2020 at 9:10 AM Matthew Brown <matthewmatthew@gmail.com> > wrote: > > I love the idea! > Thanks Matthew! > > > The syntax for new objects looks a little verbose – would it be possible > to use > > > > $foo = new Foo()[ > > property1 = "hello", > > property2 = 5, > > ]; > The short answer: I don't think so. > > This is not possible (though it's arguably 'nicer'): > > new Foo()->doSomething(); // syntax error, unexpected '->' > > Not sure why, but it's necessary to wrap the instantiation in brackets: > > (new Foo())->doSomething(); // Ok > > If someone can explain why, it would be enlightening! > > Furthermore, dropping the arrow would create conflicting syntax with > array access: > > $foo[1]; // Array access, give me the element with index 1, can be > used on objects as well > $foo[a = 1]; // Property assignment... ??? > > I'll update the RFC to reflect your proposal. > > Thank you, > Jakob >
  109119
March 18, 2020 02:42 jakob@givoni.dk (Jakob Givoni)
On Tue, Mar 17, 2020 at 4:33 PM Matthew Brown <matthewmatthew@gmail.com> wrote:
> I don't think it's conflicting _if you insist on brackets_ after the new expression. PHP Parser grammar for "new" expressions is > > T_NEW class_name_reference ctor_arguments > > If you allowed the shorter syntax, ctor_arguments would allow an object_properties entry. Sounds good, but this is unfamiliar territory to me, so would you mind
giving an example of an alternative syntax you think would work?
> I'm sure Nikita could clarify, though. I know Nikita is busy but I hope he'll stop by this RFC one of these
days, as I have a few things that needs his expertise :-)
  109059
March 16, 2020 14:26 cschneid@cschneid.com (Christian Schneider)
Am 16.03.2020 um 12:48 schrieb Jakob Givoni <jakob@givoni.dk>:
> 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!
Sorry to say but the syntax look very un-PHP-like. [] suggests an array but then is uses literals and = instead of 'strings'/$vars and => which looks wrong to my PHP eye. Apart from that it feels weird that you have an object where you want to initialise so many properties manually instead of through some sort of constructor. Is it more of a record than an object? I'm not sure if I that is a pattern I would want to encourage. My $.02, - Chris
  109085
March 17, 2020 01:22 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 9:26 AM Christian Schneider
<cschneid@cschneid.com> wrote:
> [] suggests an array but then is uses literals and = instead of 'strings'/$vars and => which looks wrong to my PHP eye. That's ok, square brackets are usually related to arrays and what I
want is something similar to array literals. The rest of the syntax is exactly the same as when you assign properties on a object currently.
> you want to initialise so many properties manually instead of through some sort of constructor. Yes, exactly. From the RFC:
"The purpose of this feature is to lighten the effort of populating data structures, especially medium to large ones." And as I say, since we don't have named parameters, this is a pragmatic alternative.
  109060
March 16, 2020 14:30 ocramius@gmail.com (Marco Pivetta)
Hey Jakob,

What happens if you have an expression that throws?

class Foo
{
    public $a;
    public $b;
    public $c;
}

$instance = new Foo();

function iThrow() {
    throw new \Exception();
}

try {
    $foo ->[
        a = 'a',
        b = iThrow(),
        c = 'c',
    ];
} catch (\Throwable $e) {
    var_export($foo); // ???
}

What will the state of `$foo` be here?

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/


On Mon, Mar 16, 2020 at 12:48 PM Jakob Givoni <jakob@givoni.dk> 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 > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > >
  109086
March 17, 2020 01:26 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 9:31 AM Marco Pivetta <ocramius@gmail.com> wrote:
> What happens if you have an expression that throws? > > class Foo > { > public $a; > public $b; > public $c; > } > > $instance = new Foo(); > > function iThrow() { > throw new \Exception(); > } > > try { > $foo ->[ > a = 'a', > b = iThrow(), > c = 'c', > ]; > } catch (\Throwable $e) { > var_export($foo); // ??? > }
Hi Marco! Trivial question - let's see what happens: Just replace COPA with the old syntax and run it: try { $foo->a = 'a'; $foo->b = iThrow(); $foo->x = 'c'; } catch (\Throwable $e) { var_export($foo); // ??? } Result: Foo::__set_state(array( 'a' => 'a', 'b' => NULL, 'c' => NULL, )) So the first property will be set, the rest will be left as they were. Best, Jakob
  109087
March 17, 2020 01:29 ocramius@gmail.com (Marco Pivetta)
Hey Jakob,

On Tue, Mar 17, 2020, 02:27 Jakob Givoni <jakob@givoni.dk> wrote:

> On Mon, Mar 16, 2020 at 9:31 AM Marco Pivetta <ocramius@gmail.com> wrote: > > What happens if you have an expression that throws? > > > > class Foo > > { > > public $a; > > public $b; > > public $c; > > } > > > > $instance = new Foo(); > > > > function iThrow() { > > throw new \Exception(); > > } > > > > try { > > $foo ->[ > > a = 'a', > > b = iThrow(), > > c = 'c', > > ]; > > } catch (\Throwable $e) { > > var_export($foo); // ??? > > } > > Hi Marco! > Trivial question - let's see what happens: > > Just replace COPA with the old syntax and run it: > > try { > $foo->a = 'a'; > $foo->b = iThrow(); > $foo->x = 'c'; > } catch (\Throwable $e) { > var_export($foo); // ??? > } > > Result: > Foo::__set_state(array( > 'a' => 'a', > 'b' => NULL, > 'c' => NULL, > )) > > So the first property will be set, the rest will be left as they were. >
That kinda makes the entire feature quite useless/uninteresting to me: if a this does is desugaring into a set of assignments, then I'm not sure what its advantage is. I was kinda hoping for an atomic state mutation across multiple fields, heh...
>
  109090
March 17, 2020 01:49 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 8:29 PM Marco Pivetta <ocramius@gmail.com> wrote:
> That kinda makes the entire feature quite useless/uninteresting to me: if a this does is desugaring into a set of assignments, then I'm not sure what its advantage is. I'm sorry about that, but the motivation of the RFC is quite clear in
the "Motivation" section. If those goals are not interesting to you then COPA won't help you.
> I was kinda hoping for an atomic state mutation across multiple fields, heh... Sounds like another RFC (that may make it in PHP 9.x+ ;-D)
  109063
March 16, 2020 15:40 rowan.collins@gmail.com (Rowan Tommins)
On Mon, 16 Mar 2020 at 11:48, Jakob Givoni <jakob@givoni.dk> wrote:

> https://wiki.php.net/rfc/compact-object-property-assignment > - A pragmatic approach to object literals > > Let me know what you think! >
Hi Jakob, Thanks for having another go at this feature, which I think a lot of people would like in some form. I think I agree with Matthew that the almost-but-not-quite array syntax looks a bit odd, but that's something that can be worked on if we agree the basic idea is sound. I fear that the need to directly set public properties (or use __set) would limit the use cases of this somewhat. I can see two ways we could arrive at something more broadly useful: * A syntax like this, plus better support for property setters (inline like in C# etc, rather than needing __set) * Named parameters plus short-hand constructor definitions (e.g. function __construct($this->foo) removing the need to type $this->foo = $foo) Maybe we want to have all four, but that would leave us with a lot of different ways of initialising objects, which might not be such a good thing. You mention using "argument bag" objects in place of named parameters, but that feels like it would be even more awkward than using an associative array. To get the example in the RFC doing something useful, you'd need quite a lot of boilerplate: class FooOptions { string $mane; string $hum; } class Foo { string $mane; string $hum; public function __construct(FooOptions $options) { // Still have to check for uninitialized properties, since COPA won't enforce them if ( ! isset($options->mane) || ! isset($options->hum) ) { throw new Exception('Bad options'); } // Still have to copy parameters one at a time $this->mane = $options->mane; $this-> hum = $options->hum; } } $myFoo = new Foo((new FooOptions())->[ mane = 'get', hum = 'life', ]); Compare that to named parameters (picking a syntax that looks similar to yours), even without any new constructor syntax: class Foo { string $mane; string $hum; public function __construct(string $mane, string $hum) { // Type and mandatory param checks are automatic // Still have to copy parameters one at a time, unless we $this->mane = $mane; $this-> hum = $hum; } } $myFoo = new Foo([ mane = 'get', hum = 'life', ]); Writing that out also made me realise a key difference between this and constructor short-hands, which is that COPA can only validate individual parameters, not the whole object; so it's hard to complain if the user forgets a mandatory field. Sometimes that wouldn't matter, but again, it limits the cases where this syntax would be useful, even if we had property setters. Regards, -- Rowan Tommins [IMSoP]
  109089
March 17, 2020 01:47 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 10:40 AM Rowan Tommins collins@gmail.com> wrote:
> Thanks for having another go at this feature, which I think a lot of people > would like in some form. I agree!
> Maybe we want to have all four, but that would leave us with a lot of > different ways of initialising objects, which might not be such a good > thing. Remember that the RFC explicitly says it's not an object initializer,
nor does it solve "named parameters" which you mention. If I had the choice, I'd go with named parameters when creating an object, but I don't and this is the next best thing. It's simple and it doesn't introduce any new concepts. It just allows you to do something inline that you could until now only do line by line.
> You mention using "argument bag" objects in place of named parameters, but > that feels like it would be even more awkward than using an associative > array. The associative array is a common pattern, but it defeats name and
type checking. An Options class add almost no extra boilerplate since you simply move the properties from the main class to the Options class. Notice that in contrary to your example, I simply copy the Options object whole into the main class.
> COPA can only validate individual > parameters, not the whole object; so it's hard to complain if the user > forgets a mandatory field Correct, the goals for COPA are quite clear in the "Motivation"
section and that kind of validation is not one of them Luckily you can still do things the way you prefer without COPA if it doesn't suit you :-) Best, Jakob
  109105
March 17, 2020 14:30 rowan.collins@gmail.com (Rowan Tommins)
On Tue, 17 Mar 2020 at 01:47, Jakob Givoni <jakob@givoni.dk> wrote:

> Remember that the RFC explicitly says it's not an object initializer, > nor does it solve "named parameters" which you mention. >
I wasn't expecting COPA to "solve" named parameters, just thinking that if we already had named parameters, we might not bother with COPA. That said, your "argument bag" example looks very much like it's trying to solve named parameters to me.
> An Options class add almost no extra boilerplate since you simply move > the properties from > the main class to the Options class. > Notice that in contrary to your example, I simply copy the Options > object whole into the main class. >
Hm, I see, that does reduce the boilerplate somewhat, although it's still split across two classes, and probably therefore two files, which is not great. You're missing some code in your example, though, because you've documented one of the options as optional, implying the others should be mandatory; in which case you need something like this in the constructor: if ( ! isset($options->mane) || ! isset($options->hum) ) { throw new Exception('Bad options'); } Which would soon get longer with more complex options. Maybe it would be refactored out into $options->isValid() or something, but it would have to go somewhere, or you'll just get "uninitialized property" errors in random parts of your application. You'd also want to copy the property onto the real object if it was initialising state rather than retaining a constant value; it would be a bit weird to write $this->options->counter++ instead of $this->counter++
> > > COPA can only validate individual > > parameters, not the whole object; so it's hard to complain if the user > > forgets a mandatory field > Correct, the goals for COPA are quite clear in the "Motivation" > section and that kind of validation > is not one of them > Luckily you can still do things the way you prefer without COPA if it > doesn't suit you :-) >
It's not so much about preferring different styles, it's about what circumstances this will be useful. It seems pretty rare that an object would have no mandatory properties, so saying "if you have a mandatory property, COPA is not for you" is ruling out a lot of uses. It might be interesting to have the syntax run before the constructor rather than after, or trigger some other magic method which could do tidying and validation, so it could apply to more circumstances. Regards, -- Rowan Tommins [IMSoP]
  109120
March 18, 2020 02:57 jakob@givoni.dk (Jakob Givoni)
On Tue, Mar 17, 2020 at 9:31 AM Rowan Tommins collins@gmail.com> wrote:
> Hm, I see, that does reduce the boilerplate somewhat, although it's still > split across two classes, and probably therefore two files, which is not > great. As an alternative to passive associative arrays, it's a small price to pay for
splitting concerns and having a documented signature for the data structure. Named parameters is another alternative (unfortunately outside reach for now) that would work great for a limited number of arguments. COPA does not make named parameters obsolete, but works great for any number of arguments.
> You're missing some code in your example, though, because you've documented > one of the options as optional, implying the others should be mandatory; in > which case you need something like this in the constructor: I've rewritten parts of the RFC and some examples substantially,
and added your view of mandatory arguments in the "Open Issues" section.
> It might be interesting to have the syntax run before the constructor > rather than after, or trigger some other magic method which could do > tidying and validation, so it could apply to more circumstances. Hmmm, in the Write Once Properties RFC they seem to believe
that object construction is a "fuzzy" term and that lazy initialization is a feature. We can add better 'automagic' support for mandatory arguments, filtering and validation in incremental proposals, to avoid biting off more than we can chew, but we have to start somewhere.
  109091
March 17, 2020 02:07 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 6:48 AM Jakob Givoni <jakob@givoni.dk> wrote:
> Let me know what you think!
Thank you for your feedback so far! I'd be really curios to know what authors of the referenced RFCs think about this, f.ex. Michał (brzuchal@php.net), Andrey (andrewgrom@rambler.ru) and Nikita (nikic@php.net) Is simple inline object population useful in itself? Is the proposed implementation as trivial as I think it is? Best regards, Jakob
  109106
March 17, 2020 15:52 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
Hi Jakob,

wt., 17 mar 2020 o 03:08 Jakob Givoni <jakob@givoni.dk> napisał(a):

> On Mon, Mar 16, 2020 at 6:48 AM Jakob Givoni <jakob@givoni.dk> wrote: > > Let me know what you think! > > Thank you for your feedback so far! > > I'd be really curios to know what authors of the referenced RFCs think > about this, f.ex. > Michał (brzuchal@php.net), Andrey (andrewgrom@rambler.ru) and Nikita > (nikic@php.net) > > Is simple inline object population useful in itself? > Is the proposed implementation as trivial as I think it is? >
For object initializer, I was hoping to introduce a feature which with the benefits of typed properties could reduce the boilerplate on initializing object and setting their properties in one expression. This is somewhat what I personally do a lot for commands and events construction where those simply have public typed properties and I don't care if something would be changed in the meantime. With current RFC for write-once, I can see object initializer could be an awesome feature with a combine of read-only properties. Currently I would have to do a lot of: $command = new SomeCommand(); $command->foo = 'bar'; $command->baz = true $this->dispatch($command); For SomeCommand looking like (with read-only for example purposes) class SomeCommand { public readonly string $foo; public readonly bool $baz; } With object initializer, this could be reduced to: $this->dispatch(new SomeCommand { foo = 'bar', baz = false }); But as mentioned IMO this is a different feature than what you propose and personally I see no point in reducing only assignment statements without combining it with object construction for these kinds of small objects, DTO's, commands, queries and events. And agree with others that brackets look unnatural for anything related to objects. IIRC there were many questions about named parameters to pass for object constructor or proper property setters like in C#, but personally I don't need a constructor at all in those cases since we have typed properties and it looks like they could be also marked as read-only in next major PHP version. Cheers, -- Michał Brzuchalski
  109118
March 18, 2020 02:36 jakob@givoni.dk (Jakob Givoni)
Thank you, Michał, for chiming in :-)

On Tue, Mar 17, 2020 at 10:52 AM Michał Brzuchalski
brzuchalski@gmail.com> wrote:
> For object initializer, I was hoping to introduce a feature which with the benefits of typed properties > could reduce the boilerplate on initializing object and setting their properties in one expression. Exactly my motivation with COPA as well;
- Typed properties - check, - Reduce boilerplate - check, - Initializing and setting properties in one expression - check.
> With object initializer, this could be reduced to: > > $this->dispatch(new SomeCommand { foo = 'bar', baz = false }); And with COPA it would be;
$this->dispatch((new SomeCommand)->[ foo = 'bar', baz = false ]); Subtle differences, when compared to the currently available alternative.
> But as mentioned IMO this is a different feature than what you propose and personally I see no point > in reducing only assignment statements without combining it with object construction for these kinds > of small objects, DTO's, commands, queries and events. Maybe you missed that COPA can be combined with object construction?
> but personally I don't need a constructor at all in those cases since we > have typed properties and it looks like they could be also marked as read-only in next major PHP version. Exactly, and as I couldn't help notice that you voted for the Write
Once Properties RFC, which clearly states that object construction is a fuzzy term (meaning don't take it too seriously) and lazy initialization is a feature... I hope you will either reconsider your support for COPA or let me know what I'm missing so I can consider other directions.
  109122
March 18, 2020 05:27 michal.brzuchalski@gmail.com (=?UTF-8?Q?Micha=C5=82_Brzuchalski?=)
śr., 18 mar 2020, 03:36 użytkownik Jakob Givoni <jakob@givoni.dk> napisał:

> Thank you, Michał, for chiming in :-) > > On Tue, Mar 17, 2020 at 10:52 AM Michał Brzuchalski > brzuchalski@gmail.com> wrote: > > For object initializer, I was hoping to introduce a feature which with > the benefits of typed properties > > could reduce the boilerplate on initializing object and setting their > properties in one expression. > Exactly my motivation with COPA as well; > - Typed properties - check, > - Reduce boilerplate - check, > - Initializing and setting properties in one expression - check. > > > With object initializer, this could be reduced to: > > > > $this->dispatch(new SomeCommand { foo = 'bar', baz = false }); > And with COPA it would be; > $this->dispatch((new SomeCommand)->[ foo = 'bar', baz = false ]); > Subtle differences, when compared to the currently available alternative. >
The difference is in object state initialization : Using Object Initializer enforce that if a class is instantiated with the Object Initializer, at the end of the instantiation and properties initialization, all visible properties *(depends on initialization scope)* are initialized, otherwise, a RuntimeException is thrown. This helps to avoid bugs where a property is added to the class but forgot to be assigned it a value in all cases where the class is instantiated and initialized. https://wiki.php.net/rfc/object-initializer#restrictions You can't do that with COPA cause it has nothing to do with object instantiation.
> > But as mentioned IMO this is a different feature than what you propose > and personally I see no point > > in reducing only assignment statements without combining it with object > construction for these kinds > > of small objects, DTO's, commands, queries and events. > Maybe you missed that COPA can be combined with object construction? > > > but personally I don't need a constructor at all in those cases since we > > have typed properties and it looks like they could be also marked as > read-only in next major PHP version. > Exactly, and as I couldn't help notice that you voted for the Write > Once Properties RFC, which clearly states that > object construction is a fuzzy term (meaning don't take it too > seriously) and lazy initialization is a feature... > > I hope you will either reconsider your support for COPA or let me know > what I'm missing so I can > consider other directions. >
  109175
March 20, 2020 23:47 jakob@givoni.dk (Jakob Givoni)
On Wed, Mar 18, 2020 at 12:27 AM Michał Brzuchalski
brzuchalski@gmail.com> wrote:

> Using Object Initializer enforce that if a class is instantiated with the Object Initializer, > at the end of the instantiation and properties initialization, all visible properties > (depends on initialization scope) are initialized, otherwise, a RuntimeException is thrown. > This helps to avoid bugs where a property is added to the class but forgot to be assigned > it a value in all cases where the class is instantiated and initialized. https://wiki.php.net/rfc/object-initializer#restrictions
Got it. Out of curiosity, would you be able to summarize why you believe your proposal was not accepted?
  109121
March 18, 2020 03:02 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 9:07 PM Jakob Givoni <jakob@givoni.dk> wrote:
> Thank you for your feedback so far! I've rewritten parts of the RFC substantially
(https://wiki.php.net/rfc/compact-object-property-assignment) so take another look if you too have ever wanted to create, populate and send an object inside a function call.
  109181
March 21, 2020 18:31 ajf@ajf.me (Andrea Faulds)
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
  109182
March 21, 2020 18:56 cmbecker69@gmx.de ("Christoph M. Becker")
On 21.03.2020 at 19:31, Andrea Faulds wrote:

> 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. :)
This is exactly what the recently declined Object Initializer RFC[1] proposed. :) [1] <https://wiki.php.net/rfc/object-initializer> -- Christoph M. Becker
  109405
March 28, 2020 21:37 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 16, 2020 at 6:48 AM Jakob Givoni <jakob@givoni.dk> 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
Hi again, Since the two weeks mandatory discussion period is nearing its end and there hasn't been any discussion activity for almost a week I'm planning on opening the vote for COPA on Monday. The RFC has been streamlined and updated to reflect all the discussion points raised, - a couple of them are now in the Rejected Features section and only the syntax question is still in the Open Issues section. I haven't received any feedback on my proposed alternative syntaxes so I guess we'll just put it to a vote (though I'm kind of sad that nobody with solid internals experience has commented on the implementability of any of them). It's my first RFC, I know its a tough sell and I'm not expecting to be successful the first time - I respect the vote 100%! I really believe that COPA can help thousands of PHP developers without introducing any new complexities to the language and my hope is that perfect won't be the enemy of good this time around :-) Any last words unsaid before the final lap commences? Best regards, Jakob
  109413
March 29, 2020 15:00 rowan.collins@gmail.com (Rowan Tommins)
On 28/03/2020 21:37, Jakob Givoni wrote:
> I really believe that COPA can help thousands of PHP developers > without introducing any new complexities to the language and my hope > is that perfect won't be the enemy of good this time around :-) > > Any last words unsaid before the final lap commences?
Hi Jakob, It occurred to me thinking about alternative syntaxes that COPA could be seen as a limited form of the "with" statement found in some languages, e.g. JS [1], VisualBasic [2], Delphi [3], Groovy [4] (note that with blocks in Python are something different). [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with [2] https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/with-end-with-statement [3] http://www.delphibasics.co.uk/RTL.asp?Name=With [4] https://docs.groovy-lang.org/latest/html/groovy-jdk/java/lang/Object.html#with(boolean,%20groovy.lang.Closure) The Groovy version is particularly relevant, since it can be used as an expression, not just a statement block, so this example from your RFC: doTheFoo((new Foo)->[     a = 1,     b = 2,     c = 3, ]); would I think look something like this in Groovy: doTheFoo(new Foo().with(true) {     a = 1     b = 2     c = 3 }) The notable differences between COPA and with blocks are: - with statements generally allow methods as well as properties to be referenced on the given object - with blocks contain a series of full statements in some form (either a syntactical block, or some form of closure); COPA instead contains a special list of key-value pairs - with blocks generally fall back to other scopes if a property or method is not found, and are often criticised for the resulting ambiguity COPA trades the scope ambiguity for reduced flexibility: the left-hand side of each assignment is always a property name, and the right-hand-side is a normal expression, so doesn't benefit from the syntax. This example from the RFC: $myObj->[     foo = 10,     bar = $myObj->foo + 20, ]; Wouldn't need the extra reference to $myObj in Groovy: myObj.with {     foo = 10     bar = foo + 20 } Similarly, the nesting example in Future Scope: $foo->[     a = 1,     b = $foo->b->[         c = 2,     ], ]; Could be written something like this: foo.with {     a = 1     b = b.tap {         c = 2     } } If we used a different sigil instead of $ for "property and method of with'd object", we could avoid the ambiguity of most with blocks, but get most of the power; something like this: $foo = new Foo with {     ->a = 1;     ->b = ->1 + 10;      ->c = new Bar with {            ->d = 'Hello';      };     ->start(); } I'm not sure whether I like this idea or not, but I thought I'd share it, because I think COPA as currently proposed is too narrow a use case to deserve a special syntax. Regards, -- Rowan Tommins (né Collins) [IMSoP]
  109414
March 29, 2020 15:31 ajf@ajf.me (Andrea Faulds)
Hi Rowan,

Rowan Tommins wrote:
> > Hi Jakob, > > It occurred to me thinking about alternative syntaxes that COPA could be > seen as a limited form of the "with" statement found in some languages, > e.g. JS [1], VisualBasic [2], Delphi [3], Groovy [4] (note that with > blocks in Python are something different).
This is a good point, though thinking about it made me realise you can already implement something like the proposed syntax in userland PHP: (function ($obj) { $foo = "foo"; $bar = "bar"; $baz = "baz"; $vars = get_defined_vars(); foreach ($vars as $key => $value) { $obj->$key = $value; } })($object); It's not very elegant though, and unfortunately you can't move the get_defined_vars() part to another function. You could do: use function \get_defined_vars as gdv; function assign(object $object, callable $assigner) { foreach ($assigner() as $key => $value) { $object->$key = $value; } } $object = new stdClass; assign($object, function () { $foo = "foo"; $bar = "bar"; $baz = "baz"; return gdv(); }); (By the way, if you want to reference existing properties, you can add an extra foreach loop to import them into the current scope, or use extract().) But then I realise that you don't even need the closure, you can just use a normal array, and it feels less necessary to add this to PHP core. If using an assign() function is inconvenient, it could be part of an object's constructor. Hmm… Thanks, Andrea
  109421
March 29, 2020 20:57 jakob@givoni.dk (Jakob Givoni)
Hi Rowan,

On Sun, Mar 29, 2020 at 10:00 AM Rowan Tommins collins@gmail.com>
wrote:

> > myObj.with { > foo = 10 > bar = foo + 20 > } >
I really like the suggested "with" syntax, - in fact I had contemplated something like that along the way. The slight "problem", I think, is that, as you mention, adding a fully fledged "with" syntax would imply that you could do a lot more than simply assigning values to properties. And while I agree that that would be cool, it feels like overkill for the actual problem COPA is trying to solve. Do you think a narrow version of "with" syntax could be incorporated into COPA without causing frustration? Or would it be wise to give it its own RFC? I haven't researched if there have already been RFCs proposing something along the lines of "with", and as such I have no idea if it has already been discussed and found problematic.
> I'm not sure whether I like this idea or not, but I thought I'd share > it, because I think COPA as currently proposed is too narrow a use case > to deserve a special syntax. >
I understand and fully agree that COPA is narrow, but I don't really understand why that's a problem - I proposed it exactly because I felt that its simplicity is its force. Low hanging fruit is usually something I would encourage to go after. I believe it's a trivial implementation that can help in uncountable situations where you just need to assign values to a predefined data structure in a single expression. I'd really like to hear the arguments against such a cost-benefit calculation. Cheers, Jakob
  109434
March 29, 2020 21:59 larry@garfieldtech.com ("Larry Garfield")
On Sun, Mar 29, 2020, at 3:57 PM, Jakob Givoni wrote:
> Hi Rowan, > > On Sun, Mar 29, 2020 at 10:00 AM Rowan Tommins collins@gmail.com> > wrote: > > > > > myObj.with { > > foo = 10 > > bar = foo + 20 > > } > > > > I really like the suggested "with" syntax, - in fact I had > contemplated something like that along the way. > The slight "problem", I think, is that, as you mention, adding a fully > fledged "with" syntax would imply that you could do a lot more than simply > assigning values to properties. > And while I agree that that would be cool, it feels like overkill for the > actual problem COPA is trying to solve. > Do you think a narrow version of "with" syntax could be incorporated into > COPA without causing frustration? Or would it be wise to give it its own > RFC? > > I haven't researched if there have already been RFCs proposing something > along the lines of "with", and as such I have no idea if it has already > been discussed and found problematic. > > > > I'm not sure whether I like this idea or not, but I thought I'd share > > it, because I think COPA as currently proposed is too narrow a use case > > to deserve a special syntax. > > > > I understand and fully agree that COPA is narrow, but I don't really > understand why that's a problem - I proposed it exactly because I felt that > its simplicity is its force. > Low hanging fruit is usually something I would encourage to go after. > I believe it's a trivial implementation that can help in uncountable > situations where you just need to assign values to a predefined data > structure in a single expression. > > I'd really like to hear the arguments against such a cost-benefit > calculation. > > Cheers, > Jakob
I went into this in my earlier Object Ergonomics post, but in short, it's quite possible for a solution to be *too* narrow. It becomes useful in too small a subset of cases to justify its added conceptual weight (and contrary to the view of some, "if you don't like it don't use it" is just not a thing when you're working in OSS, because someone is going to use it and you'll inherit that code). A narrow solution can also inadvertently serve to make something too easy that should be done rarely. In this case, the problem with COPA as proposed is that it only works for public properties that are assigned literally. That is, in my experience, a very rare case. Most objects want and need to have private or protected properties for a large variety of reasons, which would make COPA useless. Or it would nudge users toward making more properties public so that they can use the shorter COPA, but in the absence of a readonly keyword, asymmetric visibility, property accessor, or something along those lines that is a net loss as it means more properties become public when they really shouldn't be. In that case, a broader, less narrow solution is superior: Look at the actual pain points generally, find out their common elements, and address those. IMO, the combination of constructor promotion and named parameters would have a much better ROI than a dedicated syntax, it would not suffer from the public properties problem, it would still allow for constructor parameters that are not a 1:1 map to properties, but it would still serve to greatly reduce the amount of typing needed. That is, that approach offers more functionality for roughly the same or less additional syntax. In short, the cost-benefit calculation says this is useful in too narrow a case, and has the potential to encourage bad design in the name of typing less. Other alternatives address that problem space better. --Larry Garfield
  109473
March 31, 2020 01:58 jakob@givoni.dk (Jakob Givoni)
Hi Larry!

I have a lot of respect for the vision you're working on. Great
advances sometimes come out of great visions.
But let's not forget that so far it's only a vision and not all
visions come to fruition. We don't know - at the moment it's anybody's
guess.

At this point I hardly expect you to change your mind, and it's not
that you don't have all the right in the world to an opinion, but it
seems to me sometimes it's easy to confuse opinion with fact. Hence,
for the sake of my own sanity I will reply to some of your comments.
If you feel we're going around in circles, feel free to ignore my
replies. For sure, no need to double down on our disagreements.

On Sun, Mar 29, 2020 at 4:59 PM Larry Garfield <larry@garfieldtech.com> wrote:
> > I went into this in my earlier Object Ergonomics post, but in short, it's quite possible for a solution to be *too* narrow. > It becomes useful in too small a subset of cases to justify its added conceptual weight.
And what exactly is the added conceptual weight of COPA? As I've stated time and time again, COPA doesn't introduce any new concepts or complexities. If you disagree with that, I'd really like to hear exactly what those new concepts or complexities amount to in your eyes.
> (and contrary to the view of some, "if you don't like it don't use it" is just not a thing when you're working in OSS, > because someone is going to use it and you'll inherit that code).
Yeah, God forbid such madness! :-D
> A narrow solution can also inadvertently serve to make something too easy that should be done rarely. > [...] > Or it would nudge users toward making more properties public so that they can use the shorter COPA, > but in the absence of a readonly keyword, asymmetric visibility, property accessor, or something along those > lines that is a net loss as it means more properties become public when they really shouldn't be.
Hmmm, record-like data structures (structs?) - devils work in disguise, for sure... :-D If I were being arrogant I'd say that maybe allowing a trailing comma in parameter lists will nudge users towards making methods take more parameters than they should. But I think it's prudent to be modest in such judgements.
> In this case, the problem with COPA as proposed is that it only works for public properties that are assigned literally. That is, in my experience, a very rare case.
You see, here's the funny thing: It's rare because it's a hassle! *MY* experience (I do have some 20 years' worth of such...) is that people tend to use associative arrays instead for data records and the like. COPA aims to change that. And it's not true that the values have to be assigned literally - the assignment can invoke a magic method which can validate and modify a value and store it privately. I'm not saying that is good or bad, just that it's possible and that fact should not be misrepresented.
> Most objects want and need to have private or protected properties for a large variety of reasons, which would make COPA useless.
Ooops, careful with such an overstatement, buddy! I don't want to enter into this debate here, just point out that this generalisation is overreaching. Again, some modesty would suit the debate better. Truth before emotions also.
> IMO, the combination of constructor promotion and named parameters would have a much better ROI than a dedicated syntax, > it would not suffer from the public properties problem, it would still allow for constructor parameters that are not a 1:1 map to properties, > but it would still serve to greatly reduce the amount of typing needed. That is, that approach offers more functionality for roughly the > same or less additional syntax.
The proposed syntaxes for those features are much more complex than COPA's - I hope I'm not misrepresenting it when I say that it currently involves 2 new ways to write a constructor, moving declaration of properties inside a method signature and a whole new annotation/attribute paradigm to try to make sense of it all. And we're nowhere near consensus on any of it. The revived constructor promotion syntax cannot replace COPA without named parameters - and named parameters has not made any significant progress since 2013, unfortunately. I would love to see some form of named parameters, but I'm not holding my breath for it.
> In short, the cost-benefit calculation says this is useful in too narrow a case, and has the potential to encourage bad design in the name of typing less. > Other alternatives address that problem space better.
To list the facts: - Is COPA narrow? Yes - Is COPA useless? No - Will COPA encourage bad design and be overused? Opinion! - Will COPA encourage struct-like objects over anonymous array? Yes - Will COPA pollute the symbol/syntax space? Very little - Does COPA have any implications for future language evolution? None that have been shown so far - Is COPA trivial to implement? Yes Larry, keep up the great work with the Object Ergonomics. I'll follow it closely and contribute when I can. I will move forward with the vote soon. Based on the latest feedback I'd be surprised if it got even a single yes-vote, but I want to have this experience under my belt as well. I respect the vote. I will learn from it in any case. I only wish the vote isn't skewed by opinionated misrepresentation of COPA. Thanks for reading and code responsibly! Jakob
  109476
March 31, 2020 07:07 kjarli@gmail.com (Lynn)
Hi,

> In this case, the problem with COPA as proposed is that it only works for > public properties that are assigned literally. That is, in my experience, > a very rare case. > > You see, here's the funny thing: It's rare because it's a hassle! > *MY* experience (I do have some 20 years' worth of such...) is that > people tend to use associative arrays instead for data records and the > like. COPA aims to change that.
COPA won't make me use objects instead of arrays (in legacy code). The problem is writing a ton of classes for all array ever used, in a legacy file structure that comes with more maintenance than you'd like. What would make me use objects would probably be run-time interfaces via a return contract in combination with anonymous classes.
> > Most objects want and need to have private or protected properties for a > large variety of reasons, which would make COPA useless. > > Ooops, careful with such an overstatement, buddy! I don't want to > enter into this debate here, just point out that this generalisation > is overreaching. >
I don't remember when the last time was that I used public properties, even for the simplest data objects. Constructors provide all the features I need at this point, and I'm much more interested in making constructors have less boilerplate than their initialization. I can imagine COPA being more attractive once (public) read only properties are a thing, though even then I'd much rather use a constructor as it will let me find usages and add/swap arguments easily. Finding COPA usages of a class will be a lot harder compared to constructors. Regards, Lynn
  109478
March 31, 2020 09:21 rowan.collins@gmail.com (Rowan Tommins)
Hi Jakob,

On Tue, 31 Mar 2020 at 02:58, Jakob Givoni <jakob@givoni.dk> wrote:

> - Will COPA pollute the symbol/syntax space? Very little > - Does COPA have any implications for future language evolution? None > that have been shown so far >
COPA is by its nature a brand new syntax, and that does have implications for the language; that syntax has to be supported by whatever parser we might adopt, and in conjunction with any future syntax we add. Even if it doesn't cause ambiguity to the parser, there are only so many special syntaxes that users of the language will want to learn. As an extreme example, imagine if we had named parameters using braces and equal signs, object initialisers, and COPA: $foo = new Bar({someParam = $someValue}) { someProperty = $initialValue } -> [ someProperty = $newValue ]; I hope you agree that this combination would be horribly confusing, with each part looking similar but having different semantics. It follows that whichever of those syntaxes we accept first makes the others less likely, and that is a real cost. It is true that we sometimes risk making the perfect the enemy of the good, but there is also a risk in adopting something hastily and then finding it hard to improve later without breaking things. Regards, -- Rowan Tommins [IMSoP]
  109449
March 30, 2020 09:23 rowan.collins@gmail.com (Rowan Tommins)
Hi Jakob,

On Sun, 29 Mar 2020 at 21:57, Jakob Givoni <jakob@givoni.dk> wrote:

> > I understand and fully agree that COPA is narrow, but I don't really > understand why that's a problem - I proposed it exactly because I felt that > its simplicity is its force. > Low hanging fruit is usually something I would encourage to go after. > I believe it's a trivial implementation that can help in uncountable > situations where you just need to assign values to a predefined data > structure in a single expression. > > I'd really like to hear the arguments against such a cost-benefit > calculation. >
Others have said it reasonably well, but for me, a key point is that it reserves a new syntax, with no obvious way of reusing that syntax for any wider features in future. That weighs in on the cost side of the calculation, because syntax is a somewhat limited resource - we often have problems adding things without ambiguity in the parser, and a language with lots of single-purpose syntaxes is going to be harder to learn than one with a few multi-purpose syntaxes. If COPA was the first part of a wider set of complementary features, building on it as a base, it would be more attractive to me; but as currently proposed, it feels like any new feature in this area (object initialisers, named arguments, etc) would have to compete with it instead. Regards, -- Rowan Tommins [IMSoP]
  109442
March 30, 2020 01:06 internals@lists.php.net ("Levi Morrison via internals")
The current RFC text is not consistent with using `=` or `=>` for the
assignments. The assignment `=` is vastly more common, though, and I
don't understand why if we are using an array syntax we aren't using
`=>`.

I intend to vote no. I agree that we need to do something in this
space, but this is not it. I don't want perfect to be the enemy of
good either, but I think this still needs more work. Maybe interested
parties (including me) can collaborate off-list somewhere?
  109447
March 30, 2020 08:17 nikita.ppv@gmail.com (Nikita Popov)
On Mon, Mar 30, 2020 at 3:06 AM Levi Morrison via internals <
internals@lists.php.net> wrote:

> The current RFC text is not consistent with using `=` or `=>` for the > assignments. The assignment `=` is vastly more common, though, and I > don't understand why if we are using an array syntax we aren't using > `=>`. > > I intend to vote no. I agree that we need to do something in this > space, but this is not it. I don't want perfect to be the enemy of > good either, but I think this still needs more work. Maybe interested > parties (including me) can collaborate off-list somewhere? >
This is going to be a "no" vote from me as well. I don't think it's really possible to "save" this proposal though, at least if it remains as syntax sugar to perform multiple property assignments to one object. The syntax has two use-cases: Object initialization and everything else. I don't think it's doing a good job at solving object initialization, for reasons that others (and in particular Larry) have already pointed out in detail. And I don't really see a use case for this kind of mass property assignment outside of object initialization. I don't have much of a problem with the limitation to public properties (I love public properties!), the problem why this is unsuitable for object initialization is more that it is in practice mutually exclusive with constructors. You can either have a class that defines a constructor, in which case you can't use COPA with it (as the constructor would be doing the initialization -- ignore the argument-less case here), or you have a class without a constructor, in which case you essentially must use COPA. There's also no migration pathway between these two modes, in that switching between them is a backwards compatibility break for library consumers. And if it turns out that an object needs non-trivial construction logic at a later time, you can not easily introduce it without breaking COPA style initialization. This problem is not really limited to this proposal, it's a general problem of retrofitting object initialization syntax to a language that traditionally did not have it, and it doesn't seem to be an easy problem to solve. Regards, Nikita
  109451
March 30, 2020 13:19 jakob@givoni.dk (Jakob Givoni)
Hi Levi,

On Sun, Mar 29, 2020 at 8:06 PM Levi Morrison
morrison@datadoghq.com> wrHote:
> > The current RFC text is not consistent with using `=` or `=>` for the > assignments. The assignment `=` is vastly more common, though, and I > don't understand why if we are using an array syntax we aren't using > `=>`.
Not sure what you mean - are you saying the RFC has internal inconsistencies?
  109474
March 31, 2020 02:23 jakob@givoni.dk (Jakob Givoni)
Heads up!

I've moved the RFC to the voting phase:

https://wiki.php.net/rfc/compact-object-property-assignment

Voting is open until the end of Monday, April 13 (your time zone :-).

Good night,
Jakob
  109475
March 31, 2020 02:49 Danack@basereality.com (Dan Ackroyd)
On Tue, 31 Mar 2020 at 03:24, Jakob Givoni <jakob@givoni.dk> wrote:
> > I've moved the RFC to the voting phase: > > https://wiki.php.net/rfc/compact-object-property-assignment
Hi Jakob, Please don't forget to send a separate email announcing the voting with a separate subject. "Send an email to internals@lists.php.net announcing the start of voting for your RFC. Start a new mail thread and put “[VOTE]” in the subject. Set a deadline for voting; the minimum period is two weeks." That avoids people not seeing the vote announcement. cheers Dan Ack
  109479
March 31, 2020 11:34 jakob@givoni.dk (Jakob Givoni)
Hi Dan,

On Mon, Mar 30, 2020 at 9:50 PM Dan Ackroyd <Danack@basereality.com> wrote:
> > Please don't forget to send a separate email announcing the voting > with a separate subject.
This email already has a separate subject, right? Something else missing?
  109480
March 31, 2020 11:36 jakob@givoni.dk (Jakob Givoni)
On Mon, Mar 30, 2020 at 9:23 PM Jakob Givoni <jakob@givoni.dk> wrote:
> > Heads up! > > I've moved the RFC to the voting phase: > > https://wiki.php.net/rfc/compact-object-property-assignment > > Voting is open until the end of Monday, April 13 (your time zone :-). > > Good night, > Jakob
Hi guys, I don't understand why people are replying to this email that has [VOTE] in the subject as if it's still the discussion thread. Please let me know if there's something I can do about it. Best, Jakob
  109481
March 31, 2020 11:44 lester@lsces.uk (Lester Caine)
On 31/03/2020 12:36, Jakob Givoni wrote:
> I don't understand why people are replying to this email that has > [VOTE] in the subject as if it's still the discussion thread. > Please let me know if there's something I can do about it.
The problem Jakob is that the new message is STILL attached to the original discussion. If you simply changed the 'DISCUSSION' to 'VOTE' then your email client still had the original message links in place. The whole email process is something of a mess, and the 'correct' way would have been to start with an empty message, add a clean subject and text and then send it to the list ... -- Lester Caine - G8HFL ----------------------------- Contact - https://lsces.uk/wiki/Contact L.S.Caine Electronic Services - https://lsces.uk Model Engineers Digital Workshop - https://medw.uk Rainbow Digital Media - https://rainbowdigitalmedia.uk
  109482
March 31, 2020 11:48 jakob@givoni.dk (Jakob Givoni)
On Tue, Mar 31, 2020 at 6:45 AM Lester Caine <lester@lsces.uk> wrote:
> > The problem Jakob is that the new message is STILL attached to the > original discussion. If you simply changed the 'DISCUSSION' to 'VOTE' > then your email client still had the original message links in place. > The whole email process is something of a mess, and the 'correct' way > would have been to start with an empty message, add a clean subject and > text and then send it to the list ...
ok, terribly sorry, will do that now then thanks lester