Set.prototype.entries: indices as keys?
+1
Sets are not a linear data structure, so the order of entries in a Set is irrelevant, unlike an Array whose elements must have an explicit position. Set entries in JS have an iteration order purely to match programmer intuition (and ensure that all implementations adhere), however there is no structural importance of the order.
On Sun, Jan 18, 2015 at 4:28 AM, Axel Rauschmayer <axel at rauschma.de> wrote:
Currently the keys of the entries returned by
Set.prototype.entries()
are the same as the values:
let set = new Set(['a', 'b']); let pairs = [...set.entries()]; console.log(JSON.stringify(pairs)); // [["a","a"],["b","b”]]
To begin with: .entries()
doesn't make much sense in Sets abstraction at
all (as well as .keys()
). But the ship was sailed.
Sets are just a sugar on top of maps in ES6 (with just renamed API methods).
Given that sets are ordered, I’d use the “position” of an entry as the key: [[0,"a"],[1,"b”]]
This notation would assume that a set may have non-unique values (e.g. "a" at index 0, and "a" at index 2), and in this case it wouldn't be a set anymore.
Rationale: First, having an indices as keys makes the entries more useful. Second, destructuring already treats entries as if they had indices:
let [x,y] = set; // x='a'; y='b’;
Would this work actually? :) Destructuring does get property, which
wouldn't call set's get
method.
Dmitry Soshnikov wrote:
Would this work actually? :) Destructuring does get property, which wouldn't call set's
get
method.
See people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-destructuringassignmentevaluation -- destructuring array patterns uses the iteration protocol, which is why the line works as Axel suggested:
js> let set = new Set(['a', 'b']);
js> let [x,y] = set;
js> console.log(x, y)
a b
js> for (let elt of set) console.log(elt)
a
b
But not all iterables are indexable, nor should they be.
As you've pointed out (several times ;-), the odd duck is forEach. Set.prototype.forEach passes element as key and value. But sets cannot be indexed by values (to get booleans, as one might expect -- and even want, occasionally).
Sets should not be indexable but should be iterable. This leaves forEach with the dilemma of having a different signature on Set than Map and Array, or else taking a dummy or redundant parameter as the forEach key. Or we could leave forEach out of Set.prototype -- that's quite a better "different signature"!
Sets are not a linear data structure, so the order of entries in a Set is irrelevant, unlike an Array whose elements must have an explicit position. Set entries in JS have an iteration order purely to match programmer intuition (and ensure that all implementations adhere), however there is no structural importance of the order.
You can impose an order on the elements of a set, though. For example, Java’s SortedSet
has the methods first()
and last()
, which are occasionally useful. I agree that it feels weird to have indices attached to set elements, but it would at least make entries()
useful. You could iterate and treat the first element and/or the last element differently. But the same can be achieved by iterating over a zip()
of a set and a range()
(assuming iterable-based tool functions zip
and range
).
On Monday, January 19, 2015, Brendan Eich <brendan at mozilla.org> wrote:
See people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-destructuringassignmentevaluation -- destructuring array patterns uses the iteration protocol, which is why the line works as Axel suggested:
Ah, I see, that's great! Thanks for clarification.
Currently the keys of the entries returned by
Set.prototype.entries()
are the same as the values:let set = new Set(['a', 'b']); let pairs = [...set.entries()]; console.log(JSON.stringify(pairs)); // [["a","a"],["b","b”]]
Given that sets are ordered, I’d use the “position” of an entry as the key: [[0,"a"],[1,"b”]]
Rationale: First, having an indices as keys makes the entries more useful. Second, destructuring already treats entries as if they had indices:
let [x,y] = set; // x='a'; y='b’;