Set API

# Dmitry Soshnikov (11 years ago)

(sorry I again probably too late, if the API is already locked, very likely it has been discussed and approved, please let me know)

The API of Sets seems in inconvenient way exposes things that relates only to implementation details, but which doesn't make big sense at abstraction usage level.

In particular, the keys and entries methods. I understand that Sets are just backed by Maps, and for simplicity of the specification reuse the same iteration algorithms (which by default calls entries for maps in for-of).

But keys just doesn't make sense for sets, and the most inconvenient is callback function for forEach (and later for map and filter when they will be introduced). If devs want to analyze the set object itself, they have to repeat twice the "value" in parameters.

(new Set([1,2,3])).forEach((value, againValue, theSet) => {
  // huh? againValue?
  ...
});

Are we OK with this? Seems like removing entries, keys and providing own default @@iterator for Set which should be just values() would make it more sense from the abstraction usage perspective.

Dmitry

# Domenic Denicola (11 years ago)

+1. When reading the draft and spontaneously discovering this wierdness I was extremely surprised.

That said, Set is shipping in every major browser so it's not going to get fixed now.

# Brendan Eich (11 years ago)

Domenic Denicola wrote:

That said, Set is shipping in every major browser so it's not going to get fixed now.

Why do you say that?

# Rick Waldron (11 years ago)

The designed to match A.p.forEach parameters to reduce refactoring hazards.

# Dmitry Soshnikov (11 years ago)

On Fri, Oct 10, 2014 at 4:09 PM, Brendan Eich <brendan at mozilla.org> wrote:

Why do you say that?

Yeah, since the spec normally changes in some small parts, as e.g. with recent change to Array#last and Array#lastIndex which do not skip holes anymore (which is not the best from the compatibility with other similar methods like Array#map, Array#forEach, etc). But as long as it's a new policy, and why bother with holes if most of arrays are dense, not sparse -- probably OK, I fixed my polyfills already. This is just for the word, that browser change their implementations gradually anyway, once spec changes.

# Dmitry Soshnikov (11 years ago)

On Fri, Oct 10, 2014 at 4:12 PM, Rick Waldron <waldron.rick at gmail.com> wrote:

The designed to match A.p.forEach parameters to reduce refactoring hazards.

Don't think I can agree with this. An abstraction should be intuitive and predictable. For arrays and maps a "key" makes sense, for sets -- does not. And refactoring hazards are secondary in this sense (though, can be considered I agree).

# Dmitry Soshnikov (11 years ago)

On Fri, Oct 10, 2014 at 4:13 PM, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

Yeah, since the spec normally changes in some small parts, as e.g. with recent change to Array#last and Array#lastIndex

Err, sorry, Array#find, and Array#findIndex I meant of course (can't edit posts).

# Rick Waldron (11 years ago)

On Friday, October 10, 2014, Dmitry Soshnikov <dmitry.soshnikov at gmail.com> wrote:

Yeah, since the spec normally changes in some small parts, as e.g. with recent change to Array#last and Array#lastIndex which do not skip holes anymore (which is not the best from the compatibility with other similar methods like Array#map, Array#forEach, etc).

Clarifying: find and findIndex

# Domenic Denicola (11 years ago)

From: Brendan Eich [mailto:brendan at mozilla.org]

Domenic Denicola wrote:

That said, Set is shipping in every major browser so it's not going to get fixed now.

Why do you say that?

I would guess that, via the usual if (!window.Set) { window.Set = ... } polyfills , there is a nontrivial fraction of the web depending on the current behavior.

# Allen Wirfs-Brock (11 years ago)

An old discussion. See:

# Dmitry Soshnikov (11 years ago)

OK, thanks for the info Allen. I guess, as long as it really was designed this way (for reusable callbacks at first place), it's probably fine. Though I still can predict confusions there.

# Domenic Denicola (11 years ago)

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Allen Wirfs-Brock

An old discussion.  See:

These only address the forEach method though, and not the strange design of entries(), values(), and keys(). I guess a reusability argument could be made, but it seems strange to drive the API with the idea of wanting to reuse a Set in places people expect a Map.

# Dmitry Soshnikov (11 years ago)

Yeah, that's the purpose of an abstraction -- to hide implementation details. Sets expose implementation details. Unless it's really much easier to reuse the whole iteration protocol, it's probably will be fine (still again will be many confusions initially). But if it's easy to set default @@iterator of Sets to just values, and kill the keys() and entries(), it would be better. Although, once this is done, then the againValue parameter won't make sense in the callback and will need to be killed as well.

# Rick Waldron (11 years ago)

On Monday, October 13, 2014, Domenic Denicola <domenic at domenicdenicola.com> wrote:

These only address the forEach method though, and not the strange design of entries(), values(), and keys().

Can you be more specific, "strange" is subjective and it's not clear what your referring to.

# Dmitry Soshnikov (11 years ago)

I think this may bring the thread to bikesheading :) In this case it's less subjective, since entries() simply does not make (big, any?) sense for sets from the abstraction perspective. As well as keys(). Only user-level matters, implementations do not matter in API designs.

As long as it's already "locked" and was discussed in detail previously, I think we can just close this one, I already warned about future confusions. Reusing of a callback function could be considered as a good reason.

# Axel Rauschmayer (11 years ago)

Are we OK with this? Seems like removing entries, keys and providing own default @@iterator for Set which should be just values() would make it more sense from the abstraction usage perspective.

W.r.t. your last suggestion: that’s how the spec does it. Anything else would definitely not have made sense.

people.mozilla.org/~jorendorff/es6-draft.html#sec-set.prototype-@@iterator

# Erik Arvidsson (11 years ago)

Removing Set.prototype.entries and Set.prototype.keys might make sense. I'm not really sure why we added them. Probably for consistency.

# Dmitry Soshnikov (11 years ago)

On Tue, Oct 14, 2014 at 11:42 AM, Axel Rauschmayer <axel at rauschma.de> wrote:

W.r.t. your last suggestion: that’s how the spec does it. Anything else would definitely not have made sense.

people.mozilla.org/~jorendorff/es6-draft.html#sec-set.prototype-@@iterator

So you're saying that for-of iterates only values, but forEach values and "keys" (again values)?

var aSet = new Set([1, 2, 3]);

for (var v in aSet) {
  console.log(v); // 1, 2, 3
}

But

aSet.forEach((v, v1, theSet) => { ... });

Which is basically the same as:

for (var [v, v1] in aSet.entries()) {
  console.log(v, v1); // 1,1 2,2 3,3
}

That's said, if we remove the entries and keys, then the v1 naturally should (?) go away from the callback parameters as well, and in this case we cannot reuse the callback functions from Maps or Arrays.

# Dmitry Soshnikov (11 years ago)

(For the history of this thread to refer to it later)

At the meeting it was decided not to remove keys() and entries(), and keep the (value, againValue, set) callback params signature.

The reasons:

  • Consistency with maps and to reuse callbacks from arrays;
  • Even if it may seem a "wrong" Set abstraction, it's too late to exclude from ES6.