Le 20/01/2013 06:43, Allen Wirfs-Brock a écrit :
On Jan 19, 2013, at 8:39 PM, Brendan Eich wrote:
Allen Wirfs-Brock wrote:
...
I like the fact that you used "r" as a name above because certainly a WeakMap
can be used to define a relationship involving an immutable object o. But we shouldn't
be creating confusion by pretending that those relationships are the samething as a
property of o or anyway part of o.
Quite agree.
...
Well, then we are probably debating about how much we agree with each other.
Weakmaps and private Symbols are totally different things. Just because some
problems can be solved with either one doesn't make them equivalent.
Agreed, but the live proposal here is to use weakmaps for class private
instance methods/variables, and not have private symbols.
Then we should be close to resolving that if we agree that WeakMap are primarily useful
for represent external relationships between objects. The encapsulated state of an object
isn't this sort of external relationship and presumably "private state" is the
most intimate form of encapsulated state. It would be very misleading to both ES
programmer and implementors if what syntactically appears to be private state is
specified to have the semantics of an external relationship.
I disagree with Brendan when he says "to use weakmaps for class private
instance methods/variables"... well... it depends on what "use" means:
The spec is allowed to /use/ anything it needs to make the class private
syntax work. If the spec says that private properties are like
properties but aren't enumerated in Object.gOPN calls, fine. If the spec
says that private properties require a lookup to some object -> value
map, fine (but misleading, I agree).
A different problem is what the private syntax is decided to expand to,
which we can refer to as the "transpiler problem". Transpilers are
limited to /use/ what's available in the language. While the spec can
decide to invent new property types which aren't enumerated with
Object.gOPN, transpilers don't have this possibility.
In my opinion, the most important topic which hasn't been addressed yet
and which defines the boundaries of the 2 above points is the exact
semantics of private syntax. I'm careful to not say "private
properties", because it would imply that these things have the same
characteristics than what we know as public properties. It's pretty
clear from existing examples that we want to be able to attach values
based on names, that's a given.
A couple of questions regarding class private syntax (once again, I'm
only talking about the syntax, not private symbols):
1) Do we want ES5 property semantics (property descriptors, etc.)?
=> Because of the class encapsulation, I don't think enumerable,
configurable, writable are needed. Public methods can guard any
invariants they need.
=> No opinion yet on private getters/setters. Maybe they can be useful.
2) Do we want "private inheritance" (suggested by Brendan below)
=> No opinion yet.
But, that said, you certainly could use Weakmaps to define a style of
relationship that supports inheritance like mention above. Just create a
subclass of Weakmap like:
class WeakMapWithKeyInheritance extends Weakmap {
has(key) {
if (super.has(key)) return true;
let proto = Object.getPrototypeOf(key);
If (proto === null) return false;
return this.has(proto);
}
get(key) {
if (super.has(key)) return super.get(key);
let proto = Object.getPrototypeOf(key);
If (proto === null) return false;
return this.get(proto);
}
}
Right, but could you have "classes as sugar" including private syntax as David
proposed (based on weak maps) that can access prototype-delegated properties? (I guess
they would be 'protected' in that case.)
Yes, its is closer to what "protected" means in some languages and we may want
to add syntax at some point to make it easier to defined private/protected properties.
But it would be a very misleading and unexpected if that syntax was just sugar for
WeakMap operations. Nobody defines private state of a class with the expectation that it
has the implementation cost of maintaining an external relationship.
Once again, the spec (well... you in that case :-) ) will do whatever is
necessary to make the feature understandable by spec readers.
Transpilers will work with whatever is in the language. If they only
have weakmaps, they'll use that.
I tend to be in the same camp as those who say that they only need non-private
Symbols. But I know that there are significant segments of the developer
community who what stronger encapsulation than is offered by reflectable unique
symbols. In particular, I don't see a good way to do strong branding (which
the DOM folks demand) using only non-private Symbols. I don't see regular
WeakMaps as an viable solution to that problem because of the GC impact. We
could try to introduce a separate per instance mechanism for branding, but then
we would have yet another orthogonal feature to integrate (including with
Proxies) . Private symbols, so for, seems like smallest incremental extension
that is a practical solution for the branding use case.
Does the branding need to be dynamic? Could the problem be solved by
class private syntax?
class Branded{
private brand;
constructor(brand){
this.@brand = brand;
}
getBrand(){
return this.@brand;
}
}
class Node{
constructor(brand){
Branded.call(this, 'Node');
}
}
var n = new Node();
console.log(Branded.prototype.getBrand.call(n));
Could this work?
Once again, spec and implementations are free to see class private
syntax as object own properties regardless of what we use (weakmaps?) to
reason about the class syntax or to transpile it to.
David
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss