tc39 / proposal-class-public-fields

Stage 2 proposal for public class fields in ECMAScript
https://tc39.github.io/proposal-class-public-fields/
488 stars 25 forks source link

Proposal: Add all of the properties at once #39

Closed littledan closed 8 years ago

littledan commented 8 years ago

This is a cross-cutting proposal, also affecting private state (cc @zenparsing).

What if property declarations/private state fields were added all at once? The semantics would be set up roughly as follows:

  1. Let l be an empty List
  2. For each property declaration/private state f,
  3. If f has an initializer, evaluate it and append the value to l. Otherwise, append undefined
    1. For each property declaration/private state f,
  4. Pop the first element of l and define f to be the value of that element.

The proposal means that later initializers cannot reference earlier initializers in the same class (though subclasses can reference superclasses). One implementation downside would be that if there are many properties/fields, they might be spilled from registers to the stack, but the upside is that the number of observable states is less, which would mean fewer writes to the hidden class slot of objects (especially for interpreters/baseline compilers which would have trouble optimizing it away).

Thoughts? Thanks @verwaest for this suggestion.

zenparsing commented 8 years ago

@littledan This is very similar to the initialization semantics that I initially presented to TC39 back over a year ago. I think I let it go because I thought that there would be implementation concerns with batching up the field values. I would love to take this direction, though!

littledan commented 8 years ago

@zenparsing Is there any documentation about the details of these concerns? Or, who brought them up? The suggestion came from implementers in the V8 team as a way to make things more optimizable. All I can find in the notes is from here

[lots of discussion about initialization, resulting in punting and moving on to discussion of how these things work after initialization]

zenparsing commented 8 years ago

@littledan That's probably the extent of the documentation. I think my move away from the batching initialization was due to a couple of things:

If batching is more optimizable, then this seems like a double-win for me. I've wanted from the beginning to limit the number of observable object states.

littledan commented 8 years ago

@bakkot argued to me that, semantically, adding all the properties at once is unexpected, as following properties would not be able to see previous ones. Does anyone have an idea how important a property this is?

domenic commented 8 years ago

I feel like I have seen code in other OO languages where the initializer for a property refers to another property. It would be good if someone had a real-world example, but for now I imagine something like a class that keeps cached references to the first and last element of a linked list, like so:

class FocusChain {
  #nodes = new LinkedList(document, document.documentElement, document.body);
  #firstNode = this.#nodes.first();
  #lastNode = this.#nodes.last();

  // any manipulation methods will update all three private fields together
  // (probably in a more efficient way than using this.#nodes.last())
}

Apologies for the ad-hoc example that probably is not very realistic. It is certainly easy to imagine other, better ways of writing this example that don't run into the problem, but I hope it is somewhat illustrative of the kind of patterns I recall.

domenic commented 8 years ago

http://stackoverflow.com/q/27725571/3191 indicates that C# decided not to allow this, except for static fields. However, their reasoning appears to be that you can't reference this.#a because this is not usable (because it hasn't been initialized yet), which I believe is still under discussion. So I'm not sure it applies here.

https://books.google.com/books?id=g6axWRRpJZwC&lpg=PA472&ots=Hz2mmqFsaN&dq=java%20field%20initializers%20refer%20to%20other%20fields&pg=PA472#v=onepage&q&f=false has some more interesting info including noting that Java does not have this restriction.

littledan commented 8 years ago

OK, seems like this is not a good idea and we should add them one by one. I reverted the change for private fields.