Brendan Eich (2014-10-06T16:37:04.000Z)
forbes at lindesay.co.uk (2016-02-01T13:02:53.869Z)
Bear with me, trying to develop a half-thought. To say it with code: ```js Object.defineProperty(%IteratorPrototype%, 'map', { value: function (fun) { return function* (iter) { for (let [key, val] of iter) { yield fun(val, key); } }(this.clone()); }, configurable: true, enumerable: false, writable: true }); ``` Note the `this.clone()` call. This is novel, and required to avoid exhausting the receiver iterator. Rather than `%IterablePrototype%`, which is too generic a name (it does not imply a key/value map), we need something such as `%MaplikePrototype%` or `%CollectionPrototype%`: ```js Object.defineProperty(%CollectionPrototype%, 'map', { value: function (fun) { let result = new this.constructor(); for (let [key, val] of this) { result.set(key, val); } return result; }, configurable: true, enumerable: false, writable: true }); ``` The Collection protocol thus consists of at least `.constructor`, `@@iterator`, `.set`. (Is there a better way to clone? Don't want a new protocol where an old one will suffice!) This Collection protocol would include Map and maplikes but leaves out Set, Array, Object -- appropriately. We could just use FP-style map, filter, etc. APIs, but as argued among TC39ers, OOP wins in JS: (a) it matches built-ins; (b) it composes left to right, not inside out. This argument implies a `%CollectionPrototype%` object full of protocol-generic methods, to avoid rewriting collection methods all over the place (wherever there is a maplike), or borrowing `Map.prototype.*` references by hand and monkeypatching them into maplike prototypes. Unless I'm mistaken, the OOP-ness also implies other stuff, like a way to clone an iterator. I hope this makes sense. Comments welcome.