Names strawman ready for discussion
On Tue, Sep 7, 2010 at 4:17 PM, Sam Tobin-Hochstadt <samth at ccs.neu.edu>wrote:
I've significantly revised the private names strawman, available here:
Feedback is welcome, especially on the semantics discussion, which I hope is clearer at this point.
Thanks to Dave and Allen for their feedback. This is also planned for discussion at the next TC39 meeting.
Hi Sam, glad to see this coming together. A couple questions:
-
Given const n = new Name(); const x = Object.freeze({...}); what does x[n] = 88; do?
-
Given const n = new Name(); const x = Proxy.create(..., ...); what does x[n] = 88; do?
On Wed, Sep 8, 2010 at 2:47 AM, Mark S. Miller <erights at google.com> wrote:
On Tue, Sep 7, 2010 at 4:17 PM, Sam Tobin-Hochstadt <samth at ccs.neu.edu> wrote:
I've significantly revised the private names strawman, available here:
Feedback is welcome, especially on the semantics discussion, which I hope is clearer at this point.
Thanks to Dave and Allen for their feedback. This is also planned for discussion at the next TC39 meeting.
Hi Sam, glad to see this coming together. A couple questions:
- Given const n = new Name(); const x = Object.freeze({...}); what does x[n] = 88; do?
Produces an error, just as x["n"] would.
- Given const n = new Name(); const x = Proxy.create(..., ...); what does x[n] = 88; do?
Calls the 'set' trap of 'x' with x, n, and 88 as arguments.
On Tue, Sep 7, 2010 at 9:57 PM, Sam Tobin-Hochstadt <samth at ccs.neu.edu>wrote:
Hi Sam, glad to see this coming together. A couple questions:
- Given const n = new Name(); const x = Object.freeze({...}); what does x[n] = 88; do?
Produces an error, just as x["n"] would.
This means that Names cannot be used as virtual "expando" properties on frozen objects.
- Given
const n = new Name(); const x = Proxy.create(..., ...);
what does x[n] = 88; do?
Calls the 'set' trap of 'x' with x, n, and 88 as arguments.
I would then guess that using it as an rvalue, "x[n]", would invoke the 'get' trap of x's handler with x and n as arguments. So if x is an object of unknown provenance, n may be captured by that object and used to look up field values on other objects that should have been hidden from x.
Syntax aside, these are both semantic differences with ExplicitSoftFields. In the corresponding examples:
-
const f = ExplicitSoftField(); const x = Object.freeze({...}); f.set(x, 88); works, rather than throwing an error, because the state being mutated is in f rather than x. Unlike Names, this means that ExplicitSoftFields can be used as generic collision-free "expando" properties, even on frozen objects.
-
const f = ExplicitSoftField(); const x = Proxy.create(..., ...); f.set(x, 88); never invokes x's handler, never giving x a chance to steal f, since only x's identity is used by f to look up or store associations. Identity tests on a proxy, by design, do not trap to the handler.
Both of these seem to be compelling advantages of soft fields over names. However, I wonder if it would be possible to get the best of both worlds.
IIUC, the Names proposal converts:
private x; this.x = "foo"; this.x
into:
let x = new Name; this[x] = "foo"; this[x]
Would it be possible to instead rewrite it to:
let x = new ExplicitSoftField(); x.set(this, "foo"); x.get(this)
(using the same rules for determining the scope of 'x' as detailed in the Names proposal)
You would get the 'private' scoping of Names, and the concise syntax, without the limitations that MarkM raised. Am I missing something?
2010/9/8 Mark S. Miller <erights at google.com>
On Thu, Sep 9, 2010 at 07:08, Tom Van Cutsem <tomvc.be at gmail.com> wrote:
Both of these seem to be compelling advantages of soft fields over names. However, I wonder if it would be possible to get the best of both worlds. IIUC, the Names proposal converts: private x; this.x = "foo"; this.x
into: let x = new Name; this[x] = "foo"; this[x] Would it be possible to instead rewrite it to: let x = new ExplicitSoftField(); x.set(this, "foo"); x.get(this) (using the same rules for determining the scope of 'x' as detailed in the Names proposal) You would get the 'private' scoping of Names, and the concise syntax, without the limitations that MarkM raised. Am I missing something?
+1
x could also be a WeakMap in the sample above. This reminds me;
I still don't understand why we would want both ExplicitSoftField and WeakMap. If we make the API for WeakMap not so bare bone it can cover both use cases.
The thing I like with the Names proposal compared to using WeakMaps is that using WeakMaps feels very backwards.
On Tue, Sep 7, 2010 at 11:02 PM, Mark S. Miller <erights at google.com> wrote:
Syntax aside, these are both semantic differences with ExplicitSoftFields.
Yes, that's correct. It's certainly not our contention that Names provide an alternative to every use of WeakMaps. WeakMaps are a very useful language feature, not least because it's possible to write library functions like ExplicitSoftFields using them. However, Names serve primarily a different use case - when you want the information-hiding guarantees that lexical scope provides while still programming in a traditional JS style. Names allow economical expression of common OO encapsulation techniques, while maintaing the ES programming model.
ExplicitSoftFields intentionally stores data away from the object; Names stores the data with the object. The latter is often much more convenient and easier to reason about. I know that when I've been able to shift programs I've written from using soft fields to using real fields, the gains in code comprehensibility were noticeable.
On Thu, Sep 9, 2010 at 10:08 AM, Tom Van Cutsem <tomvc.be at gmail.com> wrote:
However, I wonder if it would be possible to get the best of both worlds. IIUC, the Names proposal converts: private x; this.x = "foo"; this.x
into: let x = new Name; this[x] = "foo"; this[x] Would it be possible to instead rewrite it to: let x = new ExplicitSoftField(); x.set(this, "foo"); x.get(this) (using the same rules for determining the scope of 'x' as detailed in the Names proposal) You would get the 'private' scoping of Names, and the concise syntax, without the limitations that MarkM raised. Am I missing something?
I don't think this will work with more sophisticated uses of names, where 'private' isn't used. For example, this function:
function lookup(obj,key) { return obj[key]; }
won't work properly without Names as real values.
I've significantly revised the private names strawman, available here:
strawman:names
Feedback is welcome, especially on the semantics discussion, which I hope is clearer at this point.
Thanks to Dave and Allen for their feedback. This is also planned for discussion at the next TC39 meeting.