Le 18/01/2013 06:47, Russell Leggett a écrit :
On Thu, Jan 17, 2013 at 9:40 PM, Kevin Smith <khs4...@gmail.com <mailto:khs4...@gmail.com>> wrote:

    It seems as if this approach to private class members also allows
    us to describe private methods in a convenient way.  Private
    methods can be attached to the _prototype_ of the private field
    object, thus avoiding per-instance allocation.  Of course, the
    correct "this" value has to be used in the expansion when calling
    the private method, but this approach appears to be compatible
    with mixins (whereas private symbols are not).

    https://gist.github.com/4561871

    Thoughts?


I've been on the fence with the debate, but I'll admit that this proposal is really winning me over. I don't know if it's too late to get this syntax in, but it would be a major win for me.
syntax details aside (especially with Domenic improvements), I agree.

I like this a lot more than private symbols.
Assuming the only valid use case for private symbols is classes, I agree

It actually feels a lot like deconstructing an abstract data type or pattern matching a case class in scala. There is something nice about keeping all that extra stuff off the actual object. I'm not sure if I'd still like it as much without the syntax, but maybe I would now.

I have do have a few questions on this, though:

1. How does this interact with proxies? I'm guessing that a proxy will not map correctly and therefore make it inaccessible. Personally, I'm ok with that.
It does not interact that well because of the this-binding. Classes have been long expected, so will be used, so proxies have to work well with them.

    class Purse {
        private balance;

        constructor(balance = 0) {
            private.balance = balance;
        }

         getBalance() { return balance; }
    }

    var p = new Purse(6);
    var pp = new Proxy(p, {});
    console.log(pp.getBalance());

We should be able to expect p and pp to act the same in all circumstances. With Kevin's expansion, pp.getBalance() throws a TypeError, because "amp.get(this)" is not an object. Proxy authors can work around that by returning functions bound to the target, but this is not free obviously (create as much bound functions as there are of (instance, method) pair).

The interaction between private syntax and proxies has the following components:
1) Do the proxy and the target act the same regarding private properties?
The answer is yes with whitelisted private symbols, no with naive weakmap-expanded private syntax (I explain non-naive below)
I think the answer should be yes here.

2) Does the proxy has a word to say about the access to the private property?
It's yes with private symbols (different trap if whitelisted or not).
The answer is yes for weakmap-expanded private syntax, but with some explanation. The proxy can't know about the private property, however, every access to something private has to be performed through something public (public accessor or method). Indeed, the class encapsulate access to private state (this isn't true of private symbols in general). Since the proxy can cut communication of public accesses, it can also cut accesses to private properties. I think that this additional simplicity weighs in favor of the removal of private symbols.

(I had a third point in mind and I forgot it...)


Above I've talked about naive weakmap-expanded private syntax. A less naive version could "override" the Proxy constructor to know about proxy -> target associations. Access to private state wouldn't start with the naive "amp.get(this)", but rather with "amp.get(proxyToFinalTarget(this) || this)". ("finalTarget" in case the target of the proxy is itself a proxy). For native syntax, we can imagine this setup exists before any code runs. The transpiler story is a bit less clear to me. I see different ways of writing class transpilers with different properties:
1) make classes incompatible with proxies
2) share (aka "leak") the proxyToFinalTarget function to transpiled classes
3) bring the full transpiler in the runtime so that classes can work with proxies (only the transpiler has access to proxyToFinalTarget) I think different users in different contexts all have a solution to their need.

2. Can I use private as a normal variable? Can it be bound to a new variable, passed as an argument, or returned from a function?
constructor(balance = 0) {
        let p = private;
p.checkNum(amount);
p.balance = balance;
    }
I would understand not going this route, but it definitely restricts access very tightly where private member or manually using a weakmap would allow it. Perhaps that edge case can just be handled by falling back to manually using a weakmap.
Mark's point about private symbol being mostly useful in the context of class convinced me that pretty much every other context can work with WeakMaps.

No opinion on your third point.

David
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to