Re: {Weak|}{Map|Set}
On Sep 14, 2011, at 9:42 PM, Kyle Simpson wrote: I too have been confused by the name weakmap...partially because the name is misleading, and partially because documentation on it is ambiguous/misleading. Specifically, weakmap really means weakkeymap, because only the key is weak, not the value. But then again, weakkeymap would be even more implementation-instead-of-semantics naming. We've discussed the naming of this abstraction several times: https://mail.mozilla.org/pipermail/es-discuss/2010-July/011465.html resulted in WeakMap name https://mail.mozilla.org/pipermail/es-discuss/2010-September/011711.html https://mail.mozilla.org/pipermail/es-discuss/2011-May/014211.html and at least two of the above threads seem to have their start in confusion over the meaning of weak in this context. I continue to think that WeakMap is a poor name (although it is much better than EphemerionMap, which it replaced). To me, weak in this context is not a meaningful term for everyday programmers. It is GC jargon. It also adds nothing to a user's conceptual model of the abstraction. If a map is a non-enumerable associative table, then you would never want to have a nonweakMap as that would simply be a leaky map, i.e a buggy map implementation. Perhaps it can be argued is that, in the case of WeakMap, the Weak really is intended to mean nonleaky/nonbuggy and that this is necessary to make this explicit because of the prevalence of leaky map implementations in other languages. I would prefer ObjectMap (the keys are restricted to objects). ObjectRegistry is another possibility that is suggestive of a primary use cases. Kyle's suggestion of Map would also be fine although I think there is a valid objection that the name is too general (and perhaps too conflict prone) given that the keys may not be values other than objects. This issue keeps coming back around, starting with different people. Perhaps the present name really is a problem and we could revisit it. Is not, my guess is that we will see the same issue again. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
The reference to private is actually in the Map, Set classes shown below. The BNF is also below: CallExpression : ... private ( AssignmentExpression ) ConstructorElement : ... PrivateVariableDefinition PrivateVariableDefinition : private ExportableDefinition class Map { private keys, vals; constructor() { private(this).keys = []; private(this).vals = []; } get(key) { const keys = private(this).keys; const i = indexOfIdentical(keys, key); return i 0 ? undefined : private(this).values[i]; } has(key) { const keys = private(this).keys; return indexOfIdentical(keys, key) = 0; } set(key, val) { const keys = private(this).keys; const vals = private(this).vals; let i = indexOfIdentical(keys, key); if (i 0) { i = keys.length; } keys[i] = key; vals[i] = val; } delete(key) { const keys = private(this).keys; const vals = private(this).vals; const i = indexOfIdentical(keys, key); if (i 0) { return false; } keys.splice(i, 1); vals.splice(i, 1); return true; } // todo: iteration } class Set { private map; constructor() { private(this).map = Map(); } has(key) { return private(this).map.has(key); } add(key) { private(this).map.set(key, true); } delete(key) { return private(this).delete(key); } // todo: iteration } From: Kam Kasravi kamkasr...@yahoo.com To: Mark S. Miller erig...@google.com Cc: es-discuss es-discuss@mozilla.org Sent: Wednesday, September 14, 2011 7:53 PM Subject: Re: {Weak|}{Map|Set} I noticed that these class definitions declare private names within the class body but not the constructor. My latest read of the class proposal was that private could only be declared within the constructor. Have I interpreted the BNF incorrectly? On Sep 14, 2011, at 6:20 PM, Mark S. Miller erig...@google.com wrote: On Wed, Sep 14, 2011 at 6:04 PM, Juan Ignacio Dopazo dopazo.j...@gmail.com wrote: On Wednesday, September 14, 2011, David Bruant david.bru...@labri.fr wrote: Also, I would like to talk a little bit about terminology. WeakMaps have their name inspired by the idea of weak references which have particular garbage-collection properties. From the developer perspective, this seems to be some sort of implementation detail they should not be aware of. As far as I know, current functions/constructors have their name inspired by the contract they fulfill rather than implementation considerations. The difference between current WeakMaps and Maps is their contract. In the latter, keys can be enumerated, in the former not. I think that this is the difference that should inspire different names rather than the implementation optimisation that is induced by this contract difference. In the last few days I had to write a piece of code that would strongly benefit from WeakMaps. I needed to store information about DOM nodes and retrieve it later, and these nodes aren't in my control so they can be detached at any time by someone else. If the references I kept were weak, I'd be sure that I wouldn't be causing a memory leak. And that's important in this case because the nodes are very likely Flash objects which can easily mean 20-50mb in memory. So knowing that a reference is weak is important information. I agree. Normally I strongly take the same position David does: emphasize semantics over implementation. But why? It is good when we can label a tool according to its purpose, rather than how it accomplishes that purpose. Associating the tool with its purpose helps us remember the right tool for the right job. Few would reach for the WeakMap tool thinking I need a non-enumerable table. Granted, there are cases when the non-enumerability is the desired feature, but those cases are rare. The common purpose of a WeakMap is rooted in our understanding, at a high level, of certain implementation costs, and our desire to avoid certain avoidable implementation costs. Generally, that is what a WeakMap is *for*. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Wed, Sep 14, 2011 at 11:47 PM, Kam Kasravi kamkasr...@yahoo.com wrote: The reference to private is actually in the Map, Set classes shown below. Hi Kam, You're correct. Fixed now. Thanks for pointing it out. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Sep 14, 2011, at 11:09 PM, Allen Wirfs-Brock wrote: I would prefer ObjectMap (the keys are restricted to objects). Now that you point it out (again), I agree. People who know a bit about GC also confuse WeakMap with WeakRef/WeakPtr, which we have only in the strawman space: http://wiki.ecmascript.org/doku.php?id=strawman:weak_references /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On 15 September 2011 09:10, Brendan Eich bren...@mozilla.com wrote: On Sep 14, 2011, at 11:09 PM, Allen Wirfs-Brock wrote: I would prefer ObjectMap (the keys are restricted to objects). Now that you point it out (again), I agree. I don't. :) It is true to some extent that WeakMap is GC jargon -- but as Mark points out, the normal use case for weak maps _is_ to ensure a certain space behaviour closely related to GC. So why obfuscate the very intent by purposely avoiding what is more or less standard terminology for it (if slightly ambiguous)? If I was a programmer looking for something like weak referencing in JS for the first time, weak is what I'd be searching for. ObjectMap would be too generic a name to catch my immediate attention. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
If I was a programmer looking for something like weak referencing in JS for the first time, weak is what I'd be searching for. But if you're actually aware of weakrefs (as I am), and you're searching for them in JS (as I was), and you see WeakMap (as I did), and you make the conclusion that Weak in the name means in fact weak references (as I did), then you probably also (as I did) assume that *all* the refs are weak. That's a failed conclusion, because only the keyrefs are weak. The name doesn't do anything to enlighten you that it only offers weak keyrefs and not weak valuerefs -- in fact, by your discovery line of reasoning, the name is almost a landmine that traps/misleads someone who does in fact know about weakrefs -- someone who didn't know about weakrefs wouldn't necessarily make the same deductive assumption by seeing weak in the name. Misleading/confusing with an API name is, IMHO, worse than less implementation-self-descriptive naming. --Kyle ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
Why constrain WeakMap to object keys, but not Map and Set ? I think it is because Weak only makes sense for object keys. However, if we base the distinction on iterability rather than weakness as David suggested, then we do not have to include an object key constraint anywhere. We could have: Map - current WeakMap minus object key constraint IterableMap - current Map Set - a WeakSet (David's above use case) minus object key constraint IterableSet - current Set This would also encourage use of the non-leaky abstractions where iterability is not a requirement. Also, what are the iteration order semantics ? Consider the following: let s = new Set // i.e. IterableSet s.add(0); s.add(1); // clearly [0,1] here s.add(0); // [1, 0] now ? s.delete(0); s.add(0); // clearly [1, 0] here let m = new Map; // i.e. IterableMap m.set(0, 2); m.set(1, 2); // clearly [0,1] here m.set(0, 2); // set to existing value // [1, 0] now ? m.set(0, 3); // actually change value // [1, 0] now ? m.delete(0); m.set(0, 2); // clearly [1, 0] here Also, for the iteration API of Map (i.e. IterableMap) and Set (i.e. IterableSet), why not integrate with iterators [1] : let m = new Map, s = new Set; ... for(i of m.iterator()) { ... } for(i of s.iterator()) { ... } [1] http://wiki.ecmascript.org/doku.php?id=harmony:iterators On Thu, Sep 15, 2011 at 2:10 AM, Brendan Eich bren...@mozilla.com wrote: On Sep 14, 2011, at 11:09 PM, Allen Wirfs-Brock wrote: I would prefer ObjectMap (the keys are restricted to objects). Now that you point it out (again), I agree. People who know a bit about GC also confuse WeakMap with WeakRef/WeakPtr, which we have only in the strawman space: http://wiki.ecmascript.org/doku.php?id=strawman:weak_references /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Thanks, Sean Eagan ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
Hi Kyle, It would be great if we found a name that suggested the full meaning of the abstraction by itself. WeakMap is certainly not that. Sometimes we find something like this. Also important is one that avoids suggesting any misunderstandings. I agree that ObjectMap beats WeakMap on those grounds. As to the importance of naming for purpose, which is the contrary argument here, I have a question for you. You say and you're searching for them in JS (as I was). Had the abstraction been called ObjectMap or ObjectRegistry, would you have found it? As it was, you found the right thing to look at and think about, but you needed to read more before you understood whether it serves your actual purpose. Was this a better outcome than not finding it? Other alternate names that were discussed in that thread, listed from my least to most favorite: * NonLeakyObjectMap // accurate and suggestive, but a mouthful * WeakKeyMap // inaccurate, less so than the conclusion Kyle lept to * EphemeralMap // accurate and suggestive, and far enough from weak to avoid quick misunderstandings The reason WeakKeyMap is technically inaccurate is that in var wkm = WeakKeyMap(); var k = {}; wkm.set(k, [k]); k = null; the k - [k] association is no longer reachable. However, because weak key maps are built on the use of a weak reference to point at the key, and to receive notification of the key's demise, no weak key map can collect the above cyclic garbage association.[1] That's what's so important about ephemerons: the collector knows about such associations, rather than knowing about the key separately from knowing about the value. That's why I like WeakMap best -- it is the mapping that is weak, not the keys or the values. Nevertheless, given the magnitude of misunderstandings people are worried about here, perhaps this technical inaccuracy is the lesser evil. But my own preference remains WeakMap first and then EphemeralMap. [1] wkm holds onto each value strongly until it notices the corresponding key's demise. In this case, the value holds onto the key strongly, so wkm has no demise to notice. On Thu, Sep 15, 2011 at 7:56 AM, Kyle Simpson get...@gmail.com wrote: If I was a programmer looking for something like weak referencing in JS for the first time, weak is what I'd be searching for. But if you're actually aware of weakrefs (as I am), and you're searching for them in JS (as I was), and you see WeakMap (as I did), and you make the conclusion that Weak in the name means in fact weak references (as I did), then you probably also (as I did) assume that *all* the refs are weak. That's a failed conclusion, because only the keyrefs are weak. The name doesn't do anything to enlighten you that it only offers weak keyrefs and not weak valuerefs -- in fact, by your discovery line of reasoning, the name is almost a landmine that traps/misleads someone who does in fact know about weakrefs -- someone who didn't know about weakrefs wouldn't necessarily make the same deductive assumption by seeing weak in the name. Misleading/confusing with an API name is, IMHO, worse than less implementation-self-**descriptive naming. --Kyle -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Sep 15, 2011, at 6:49 AM, Andreas Rossberg wrote: On 15 September 2011 09:10, Brendan Eich bren...@mozilla.com wrote: On Sep 14, 2011, at 11:09 PM, Allen Wirfs-Brock wrote: I would prefer ObjectMap (the keys are restricted to objects). Now that you point it out (again), I agree. I don't. :) It is true to some extent that WeakMap is GC jargon -- but as Mark points out, the normal use case for weak maps _is_ to ensure a certain space behaviour closely related to GC. No the normal use case for WeakMaps is simply to make associations between objects and arbitrary values. The special GC behavior is necessary to avoid memory leaks, but that is a quality of implementation issue, not a use case. The typical JS programmer who wants to form such associations is not going to be thinking about the possibility of a leaky map unless they have already been burnt by them in some other language. So why obfuscate the very intent by purposely avoiding what is more or less standard terminology for it (if slightly ambiguous)? If I was a programmer looking for something like weak referencing in JS for the first time, weak is what I'd be searching for. ObjectMap would be too generic a name to catch my immediate attention. Because, the majority of JS programmers will simply be looking for a way to map objects to values and will not be thinking about GC consequences. We want them to find this thing we are currently trying to name. We don't want them to miss it because it has weak in its name and they don't know what weak means. We need to design first for the 95% (ass generated number) of JS programmers who don't understand GC. Finally, none are good exemplars for typical JS programmers. We (and our friends) know too much and in general have a level of PL expertise that far exceeds that of the typical JS programmer. In cases such as this our expectations may be the exact opposite of a typical JS programmer. Allen ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: IDE support?
On 13 September 2011 16:48, Brendan Eich bren...@mozilla.com wrote: On Sep 13, 2011, at 5:33 AM, Andreas Rossberg wrote: * There are extra costs in space and time to doing the runtime analysis. * Compile time is runtime, so there are severe limits to how smart you can afford to get in a compiler. These are bearable apples to trade against the moldy oranges you'd make the world eat by introducing type annotations to JS. Millions of programmers would start annotating for performance, i.e., gratuitously, making a brittle world at high aggregate cost. The costs born in browsers by implementors and (this can hit users, but it's marginal) at runtime when evaluating code are less, I claim. Depends on how good you want to optimize. Aggressive compilers can be really slow. There are limits to what you can bear at runtime. Especially, when you have to iterate the process. * The massive complexity that comes with implementing all this affects stability. This one I'm less sympathetic to, since we won't get rid of untyped JS up front. A sunk cost fallacy? If we could make a clean break (ahem), sure. Otherwise this cost must be paid. Well, the counter-argument would be that you wouldn't need to care about optimising untyped code as much, if the user had the option to switch to a typed sublanguage for performance. * Wrt limits, even in the ideal case, you can only approximate the performance of typed code -- e.g. for property access you have at least two memory accesses (type and slot) plus a comparison and branch, where a typed language would only do 1 memory access. That's *not* the ideal case. Brian Hackett's type inference work in SpiderMonkey can eliminate the overhead here. Check it out. I'm actually pretty excited about that, and hope to see more on that front. Cool stuff. However, that ideal case is achieved in a relatively small percentage of cases only. Otherwise we should probably not see a (already impressive) 20-40% speed-up (IIRC), but rather something closer to 200-400%. * Type inference might mitigate some more of these cases, but will be limited to fairly local knowledge. s/might/does/ -- why did you put type inference in a subjunctive mood? Type inference in SpiderMonkey (Firefox nightlies) is not local. Fair enough re the subjunctive. Still, there are principal limitations to what type inference can do. Especially for OO. You hit on undecidable territory very quickly. You also have to give up at boundaries such as native bindings, calls to eval, or (in ES6) to the module loader, unless you're given extra information by the programmer (this is basically the separate compilation problem). So the inferencer has to work with approximations and fallbacks. For a language like JS, where a lot of conceptual polymorphism, potential mutation, and untypable operations are going on, those approximations will remain omnipresent, except, mostly, in sufficiently local contexts. Not to say that it is not worth extending the boundaries -- it definitely is. But it will only get you that far. * Omnipresent mutability is another big performance problem in itself, because most knowledge is never stable. Type annotations or (let's say) guards as for-all-time monotonic bounds on mutation are useful to programmers too, for more robust programming-in-the-large. That's a separate (and better IMHO) argument than performance. It's why they are on the Harmony agenda. Of course I'd never object to the statement that there are far better reasons to have typy features than performance. :) I just didn't mention it because it wasn't the topic of the discussion. So despite all the cool technology we use these days, it is safe to assume that we will never play in the performance league of typed languages. Unless we introduce real types into JS, of course. :) Does JS need to be as fast as Java? Would half as fast be enough? No, it doesn't have to be as fast. Not yet, at least... I estimate we have another 3 years. ;) /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Thu, Sep 15, 2011 at 8:41 AM, Sean Eagan seaneag...@gmail.com wrote: Why constrain WeakMap to object keys, but not Map and Set ? I think it is because Weak only makes sense for object keys. However, if we base the distinction on iterability rather than weakness as David suggested, then we do not have to include an object key constraint anywhere. Hi Sean, that is a perfect example of how quickly we could go from de-emphasizing the purpose to losing the purpose. With this restriction relaxed, I can well imagine programmers using large numbers or strings as keys, thinking the corresponding association would be collected when those numbers or strings no longer otherwise exist in their program. Programmers coming from languages where boxed large numbers or strings have an observable unique identity will be especially prone to fall into this trap. The result is that their program has a memory leak that remains silent until they stress their program enough to run out of memory. At which point, they may have great difficultly tracking down the cause -- especially if this misuse of *Map is buried in some library written by someone else. Given the normal invisibility of the symptom, this is quite likely. Better to error early with a clear diagnostic, so no one is confused about what keys can be usefully used. Which btw, does bring up one way in which the FF implementation of WeakMaps is too strict. By the above reasoning, we should reject non-objects in the key position of a .set(). We need not reject it in the key position of a .get(), .has(), or .delete(). All all cases, we know that a non-object key cannot correspond to any stored association, so .get(), .has(), and .delete() can respond as if for any other not-found key. We could have: Map - current WeakMap minus object key constraint IterableMap - current Map Set - a WeakSet (David's above use case) minus object key constraint IterableSet - current Set This would also encourage use of the non-leaky abstractions where iterability is not a requirement. Also, what are the iteration order semantics ? Consider the following: let s = new Set // i.e. IterableSet s.add(0); s.add(1); // clearly [0,1] here s.add(0); // [1, 0] now ? s.delete(0); s.add(0); // clearly [1, 0] here let m = new Map; // i.e. IterableMap m.set(0, 2); m.set(1, 2); // clearly [0,1] here m.set(0, 2); // set to existing value // [1, 0] now ? m.set(0, 3); // actually change value // [1, 0] now ? m.delete(0); m.set(0, 2); // clearly [1, 0] here Also, for the iteration API of Map (i.e. IterableMap) and Set (i.e. IterableSet), why not integrate with iterators [1] : let m = new Map, s = new Set; ... for(i of m.iterator()) { ... } for(i of s.iterator()) { ... } [1] http://wiki.ecmascript.org/doku.php?id=harmony:iterators On Thu, Sep 15, 2011 at 2:10 AM, Brendan Eich bren...@mozilla.com wrote: On Sep 14, 2011, at 11:09 PM, Allen Wirfs-Brock wrote: I would prefer ObjectMap (the keys are restricted to objects). Now that you point it out (again), I agree. People who know a bit about GC also confuse WeakMap with WeakRef/WeakPtr, which we have only in the strawman space: http://wiki.ecmascript.org/doku.php?id=strawman:weak_references /be ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss Thanks, Sean Eagan -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: IDE support?
On 13 September 2011 21:32, Wes Garland w...@page.ca wrote: When I write shell programs, and JS programs, I keep an extra terminal window open to a spare shell or a JS REPL. I try stuff. Stuff that works, I copy into my program. Then I run my program - which happens quickly, because the compiler is super-fast and the program is a contained entity which probably runs in a dynamically configured environment. REPLs and quasi-instant compile turn-arounds are indeed great features, but by no means exclusive to untyped languages, and never have been. It just happens that the typed languages dominating the mainstream suck badly in this area. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: IDE support?
On 14 September 2011 00:00, Brendan Eich bren...@mozilla.com wrote: So, static+dynamic. The static side has some powerful algorithms to bring to bear. Dynamic is necessary due to eval and kin, and gives strictly more information (and more relevant information!). Nitpick: I believe you are mistaken about the strictly more bit. There is information that _only_ static analysis can derive. Consider e.g. aliasing or escape analysis, or other kinds of global properties. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Thu, Sep 15, 2011 at 8:47 AM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: [...] No the normal use case for WeakMaps is simply to make associations between objects and arbitrary values. The special GC behavior is necessary to avoid memory leaks, but that is a quality of implementation issue, not a use case. The typical JS programmer who wants to form such associations is not going to be thinking about the possibility of a leaky map unless they have already been burnt by them in some other language. I do not know of a non-leak-association-map in *any* other language or library whose name does not suggest its GC role. Do you know of a counter-example? If not, then let's say ...burnt by them in every other language A programmer approaching ES6 wanting simply to make associations and not thinking about GC issues will probably reach for the (iteratable) Map anyway, which is how it should be. For them, the iterability of these maps will often be seen as a virtue. If they are unconcerned about storage, they will usually see little reason to give up on this iterability. Because, the majority of JS programmers will simply be looking for a way to map objects to values and will not be thinking about GC consequences. We want them to find this thing we are currently trying to name. We don't want them to miss it because it has weak in its name and they don't know what weak means. We need to design first for the 95% (ass generated number) of JS programmers who don't understand GC. Those programmers *should* find our interatable maps, not our weak-association maps. Finally, none are good exemplars for typical JS programmers. We (and our friends) know too much and in general have a level of PL expertise that far exceeds that of the typical JS programmer. In cases such as this our expectations may be the exact opposite of a typical JS programmer. There are many kinds and levels of programmers. For the typical programmers you talk about, I'd just point them at our current iteratable Maps and Sets. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Thu, Sep 15, 2011 at 8:41 AM, Sean Eagan seaneag...@gmail.com wrote: Also, for the iteration API of Map (i.e. IterableMap) and Set (i.e. IterableSet), why not integrate with iterators [1] : let m = new Map, s = new Set; ... for(i of m.iterator()) { ... } for(i of s.iterator()) { ... } That is the intention -- it's what that mysterious // todo: iteration note is about at http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets. At the time this was written, iterators hadn't yet settled down. Your suggestion about iteration semantics and order is helpful. Thanks. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On 15 September 2011 17:47, Allen Wirfs-Brock al...@wirfs-brock.com wrote: No the normal use case for WeakMaps is simply to make associations between objects and arbitrary values. The special GC behavior is necessary to avoid memory leaks, but that is a quality of implementation issue, not a use case. Just like with tail calls, certain space optimizations are semantically relevant, because code will rely on them and potentially break if they are not performed. /Andreas ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
You say and you're searching for them in JS (as I was). Had the abstraction been called ObjectMap or ObjectRegistry, would you have found it? I don't think the API name is the only way someone can discover what they're looking for. Proper documentation for ObjectMap which said keyrefs are held weakly or something to that respect would probably have ended up on my search radar. Of course, if the WeakMap really was both weak-key and weak-value, then I'd absolutely expect the name to be WeakMap (I think weak in this case is a useful and non-trivial part of the behavior). So my complaint is not Weak, but that Weak implies something more comprehensive than is actually the case. It over-promises and under-delivers, so to speak. I should also clarify my process for how I found this API (I over-simplified in my previous email). I actually started out with both the weakref need AND the object-as-key (map) need. For the object-as-key need, I had already constructed a dual-numerically-indexed-array solution to associating an object with a value. But then, realizing that this was not only clunky, but also was going to make manual GC (that is, cleaning up the entries if the object is removed) also more awkward/less performant, I started looking for an API that would do both: Map (object-as-key) and automatically clean up the entries in the Map if either the key-object or the value-object (in my case, both DOM objects) were GC'd. In that context (and in support of Allen's early assertions), Map in the name was most important to focus me into a (theoretical) class of APIs (if there were indeed several different kinds of maps). Then I would have searched through the documentation to see if any of the Maps had the weak behavior I was looking for. OTOH, had I *only* been looking for pure Weak References, and not a Map structure, then I'd have been looking for some API like WeakRef, and actually Map probably would have been confusing or ignorable noise. As it was, you found the right thing to look at and think about, but you needed to read more before you understood whether it serves your actual purpose. I found it because a fellow Mozilla dev said hey, that sounds like WeakMaps and I thought awesome, ask and ye shall find. Of course, the devil was in the details, because it wasn't actually what I needed completely. This was compounded by the fact that the MDN documentation (at least at the time) was ambiguous and didn't make it clear that only keys were weak. So a well-experienced co-worker and the documentation BOTH were confused (as were several others through various IRC chats) as to exactly what was and was not weak in the WeakMap. How did I figure it out? By writing it into my code, and then seeing mem-leak tests fail. Thankfully, I eventually found some IRC people who clarified that what I was seeing was not a bug but was in fact by-design. But, that's a hard way to learn the lesson. Would a more accurate name have helped? Perhaps. WeakKeyMap certainly would have made it obvious that the Map was not fully weak. Would more accurate documentation have helped? Absolutely. Would naming *and* documentation have helped other co-workers not be misled and consequently point me in the wrong path? I hope so. That's why I like WeakMap best -- it is the mapping that is weak, not the keys or the values. I understand what you're saying here. But as I mentioned before, the way my (far less informed) brain thinks about it, the map or link between two objects should in fact be weak and ephemeral enough that either side going away (being GC'd) should be enough to cause the link between the two to be cleaned up. I think it's because I tend to think of Map as more 2-way than one-way, though I understand it's technically only 1-way. Saying it a different way... if the focus is on the map or link itself, and the RHS thing the map/link is pointing to is no longer valid/defined, then what use is there keeping a link that points to something now undefined? It just seems a little unfortunate/misleading to me that from an implementation perspective, creating the map/link is sufficient to prevent the RHS value in question from ever getting to that undefined state. When I create a reference using variables/properties, I *expect* a hard reference that behaves like that. But when I use a specialized API with Weak in the name, I definitely expect the opposite. --Kyle ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: {Weak|}{Map|Set}
On Sep 15, 2011, at 9:07 AM, Mark S. Miller wrote: On Thu, Sep 15, 2011 at 8:47 AM, Allen Wirfs-Brock al...@wirfs-brock.com wrote: [...] No the normal use case for WeakMaps is simply to make associations between objects and arbitrary values. The special GC behavior is necessary to avoid memory leaks, but that is a quality of implementation issue, not a use case. The typical JS programmer who wants to form such associations is not going to be thinking about the possibility of a leaky map unless they have already been burnt by them in some other language. I do not know of a non-leak-association-map in *any* other language or library whose name does not suggest its GC role. Do you know of a counter-example? If not, then let's say ...burnt by them in every other language Probably not, but in most (if not all cases) those other languages what already used up the good names on leaky versions and needed to define more explicit names for the non-leaky versions that were later additions. We don't have that heritage. We can do our naming starting from a clean slate. My speculation is that over the long run, many more programmers will be first introduced to these data structures via JS than will come to it after already being corrupted by some other broken language. A programmer approaching ES6 wanting simply to make associations and not thinking about GC issues will probably reach for the (iteratable) Map anyway, which is how it should be. For them, the iterability of these maps will often be seen as a virtue. If they are unconcerned about storage, they will usually see little reason to give up on this iterability. iterability makes Map inherently leaky from an application logic perspective. If you place a key in a Map you must manually delete if you don't want to retain it for the full life of the map. For this reason, the fact that a map is iteratable should probably be featured in its name. Using Map as the name of iteratable associative maps is probably an attractive nuance. From that perspective, the names I suggest are: IteratableMap -- currently Map, iteratatble associations between arbitrary valued keys and values ObjectMap - currently WeakMap, non-iteratable associations between object valued keys and arbitrary values It might be even better to even further increate the conceptual distance between to two abstractions by not using map in both names. In that case, ObjectRegistry might be better than ObjectMap. Because, the majority of JS programmers will simply be looking for a way to map objects to values and will not be thinking about GC consequences. We want them to find this thing we are currently trying to name. We don't want them to miss it because it has weak in its name and they don't know what weak means. We need to design first for the 95% (ass generated number) of JS programmers who don't understand GC. Those programmers *should* find our interatable maps, not our weak-association maps. Only if they need to iterate over them. If not, the weak association maps is what they should find. (with the caveat, that I still have concerns about the potential impact of heavy use of ephemeron based maps upon GC performance.) Finally, none are good exemplars for typical JS programmers. We (and our friends) know too much and in general have a level of PL expertise that far exceeds that of the typical JS programmer. In cases such as this our expectations may be the exact opposite of a typical JS programmer. There are many kinds and levels of programmers. For the typical programmers you talk about, I'd just point them at our current iteratable Maps and Sets. However, for them, application level leaks are often a problem. Except for situations where they actually need to iterate they are better served by being pointed towards WeakMap. -- Cheers, --MarkM ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
WeakPair primitive ?
Would a WeakPair primitive be useful... let wp = new WeakPair(key, value); ... if(wp.hasKey(key)) { foo(wp.value()); } WeakMap could be built on top of this primitive: class WeakMap { constructor() { private pairs = new Set; private getPair = function(key) { for(i of private(this).pairs.iterator()) { if(i.hasKey(key)) return i; } return undefined; } } get(key) { let pair = private(this).getPair(key); return pair ? pair.value() : undefined; } has(key) { return !!private(this).getPair(key); } set(key, val) { if(!isObject(key)) throw new Error; let pair = private(this).getPair(key); let pairs = private(this).pairs; if(pair) { pairs.delete(pair); } pairs.add(new WeakPair(key, value)); } delete(key) { let pair = private(this).getPair(key); if(pair) { let pairs = private(this).pairs; pairs.delete(pair); } } } Are there other useful abstractions that could be built on top of WeakPair, beyond WeakMap ? Thanks, Sean Eagan ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: WeakPair primitive ?
On Sep 15, 2011, at 10:21 AM, Sean Eagan wrote: Would a WeakPair primitive be useful... let wp = new WeakPair(key, value); ... if(wp.hasKey(key)) { foo(wp.value()); } WeakMap could be built on top of this primitive: It's not that easy. Read http://www.arnetminer.org/dev.do?m=downloadpdfurl=http://arnetminer.org/pdf/PDFFiles/--g---g-Index1247931776950/Ephemerons A New Finalization Mechanism1247944577286.pdf You need Ephemeron pairs to build such abstractions ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: IDE support?
On Thu, Sep 15, 2011 at 9:02 AM, Andreas Rossberg rossb...@google.com wrote: On 14 September 2011 00:00, Brendan Eich bren...@mozilla.com wrote: So, static+dynamic. The static side has some powerful algorithms to bring to bear. Dynamic is necessary due to eval and kin, and gives strictly more information (and more relevant information!). Nitpick: I believe you are mistaken about the strictly more bit. There is information that _only_ static analysis can derive. Consider e.g. aliasing or escape analysis, or other kinds of global properties. There are systems that handle escape analysis cases via write barriers, no? Alias detection (or more importantly non-alias determinations) seem amenable to the assume-and-guard model used for PICs and trace selection and other code specialization patterns seen all over modern JS engines. The TraceMonkey engine tracks many global properties (including the properties of globals) to deoptimize as needed and optimize where possible; our TI and IonMonkey work goes even further. Mike ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: WeakPair primitive ?
WeakMap is in Harmony... http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps On Thu, Sep 15, 2011 at 1:47 PM, Allen Wirfs-Brock al...@wirfs-brock.comwrote: On Sep 15, 2011, at 10:21 AM, Sean Eagan wrote: Would a WeakPair primitive be useful... let wp = new WeakPair(key, value); ... if(wp.hasKey(key)) { foo(wp.value()); } WeakMap could be built on top of this primitive: It's not that easy. Read http://www.arnetminer.org/dev.do?m=downloadpdfurl=http://arnetminer.org/pdf/PDFFiles/--g---g-Index1247931776950/Ephemerons A New Finalization Mechanism1247944577286.pdf You need Ephemeron pairs to build such abstractions ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss