Closed littledan closed 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!
@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]
@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.
@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?
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.
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.
OK, seems like this is not a good idea and we should add them one by one. I reverted the change for private fields.
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:
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.