About private names

François REMY fremycompany_pub at yahoo.fr
Sun Mar 20 15:17:37 PDT 2011


If I can add my point to the discussion, I must admit I don’t like the “Private Names Proposal” either. I find it confusing and complex. As I thought I was the only one who had this in mind, I didn’t react before but if more people are confident it’s a strange proposal, maybe could the proposal be replace by something simpler and more intuitive.

When I first read the proposal, I thought we may use a new property of the property descriptors to define the “privality” of a property.

What I propose is to manage a list of all currently defined private keys. This list is managed scope by scope. Each time a <<private key>> instruction is encountered, the value of the private key that follows (or, if undefined, a new private key) is added to private keys list (shortened PKL further in the mail).

Then, I propose to add a new property to each property descriptor: privateKey. When a property is read or modified somewhere in the code, the operation can only complete if the value of getOwnProprtyDescriptor(currentProperty).privateKey is in the PKL. It will fails otherwhise (return undefined for a read operation or throw an error if an attempt is made to change its value).

    {
        private key ModulePrivate; // generate a new private key named ModulePrivate, and add it to the current scope’ PKL
    
        // Create a new global property called “doSomethingPrivate” and only accessible to scopes who have the “ModulePrivate” key
        <private: ModulePrivate> function doSomethingPrivate() {  ...  }

        // Create a new global property called “getModulePrivateKey” accessible to every scope
        function getModulePrivateKey() { return ModulePrivate; }
    
        doSomethingPrivate(); // works
    
        /* As the interpreter goes out of the scope where ModulePrivate is defined, ModulePrivate is removed from the PrivateKeys collection */
    }

    try { doSomethingPrivate(); } catch (ex) {} // throw a “undefined is not an object” exception as doSomethingPrivate returned ‘undefined’ (ModulePrivate is not in the PKL)
    private key ModulePrivate = getModulePrivateKey(); // private key += getModulePrivateKey() would works, too (in case you don’t need a reference to the key)
    try { doSomethingPrivate(); } catch (ex) {} // works

The only feature that disappeard is the ability to define more than one property having the same “apparent” name.

I personnally feel this was a bad practice, anyway. I don’t like the fact a property could change of name in function of the scope. And I find it even worse that two properties sharing the same name in two different scopes can’t share the same name in the same scope because the “property name” is become a variable and you can’t have two variables with the same name.

To make my point clear, here an example (for the purpose of the demonstration, I want to define a private method (clone) in the Obj class that can only be accessed from within the own Obj instance or by a SharedClass instance, but not within another Obj instance) :

    {
        private getPrivateName;
        function SharedClass(a, b) {
            private clone = a.getPrivateName();
            private clone2 = b.getPrivateName(); // #fail: it’s the same method, but I had to choose a different name!
            this.c = a.clone();
            this.d = b.clone2();
        }
    
        function Obj() {
            private clone;
            this.getPrivateName = function() { return #.clone; }
            this.clone = function() { ... }
        }
    }

Using my proposal, it would be cleaner :

    {
        private key SharedProp;
        function SharedClass(a, b) {
            private key += a.getPrivateName();
            private key += b.getPrivateName();
            this.c = a.clone();
            this.d = b.clone(); // same name
        }
    
        function Obj() {
            private key ObjInstancePrivate;
            this.<private: ObjInstancePrivate>clone = function() { ... }
            this.<private: SharedProp>getPrivateName = function() { 
                return ObjInstancePrivate; 
            }
        }
    }

The problem shown before can be even worse: imagine you have to work on objects in a loop, you can’t import all property names and you’ll be forced to use the [] notation in your code. It’s not the case using my proposal since you can add “anonymous” private names to the scope’ PKL.

My proposal is also simpler in the sense you don’t need to modify the fact that a property name has to be a String. It also make runtime optimisation easier to find out since you don’t need to know which ‘private names’ are loaded because only one property could have the “clone” name on the object, anyway (that the property read/write will throw an error or not hasn’t to be known at compilation time).

Any thought on this ?
Regards,
François


From: Andrew Dupont 
Sent: Sunday, March 20, 2011 6:54 AM
To: Sam Tobin-Hochstadt 
Cc: es-discuss at mozilla.org 
Subject: Re: About private names

On Mar 19, 2011, at 7:02 PM, Sam Tobin-Hochstadt wrote:

> You're correct -- this won't do what you probably intended.  But the
> great thing about private names is that this is a problem you can
> *locally* fix.  For example:
> 
> private myClone = installCloneLibrary();
> var twin = [{a:0}, {b:1}].myClone();
> var thing = MyObj.clone();

Yeah, but at that point one might as well just name the function myClone (replacing "my" with some framework-specific prefix) and eschew private names altogether. In this example, being able to name the method "clone" without fear of naming collisions is the whole point.

> or
> 
> var cloneProp = installCloneLibrary();
> var twin = [{a:0}, {b:1}][cloneProp]();
> var thing = MyObj.clone();

This is more palatable, but I wager it's far harder for end-users to grok.

Anyway, now that I've confirmed my suspicions, I'm hesitant about the private names proposal as described. The fact that declaring a certain name as private affects _all_ property name lookups in that scope (all lookups that use the dot operator or object literal syntax, at least) — well, I'm not sure I like the implications. It would mean a new  and _surprising_ distinction between dot notation and bracket notation.

As a maintainer of a framework that does quite a bit of built-in extension, I can't imagine us using private names for this purpose. If we wanted to define {}.clone in this manner, we'd be exchanging one potential collision (one property defined in one place) for another (every property defined in the same lexical scope). If the private names had their own operator (e.g., twin#clone vs. twin.clone), it'd at least be worth considering.

I'm sure private names would be useful for other reasons, but IMO it wouldn't solve the problem of safely extending built-ins.

Cheers,
Andrew
_______________________________________________
es-discuss mailing list
es-discuss at mozilla.org
https://mail.mozilla.org/listinfo/es-discuss
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110320/3f0d30d9/attachment-0001.html>


More information about the es-discuss mailing list