# Set \`.toggle\` method

**URL:** <https://es.discourse.group/t/set-toggle-method/445>\
**Category:** 💡 Ideas\
**Tags:** proposal\
**Created:** [August 28, 2020, 8:06am UTC](https://es.discourse.group/t/set-toggle-method/445 "2020-08-28T08:06:46Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [August 28, 2020, 8:06am UTC](https://es.discourse.group/t/set-toggle-method/445/1 "2020-08-28T08:06:46Z")

</div>

This would carry roughly the same kind of semantics as `DOMTokenList`, but also returning a boolean based on whether it previously existed for convenience and utility, something like this:

```javascript
Set.prototype.toggle = function (value, include = this.has(value)) {
    if (include) {
        return this.delete(value);
    } else {
        const prev = this.size;
        this.add(value);
        return this.size !== prev;
    }
};

```

I've personally had as much use for it outside the DOM as in, so it'd be very useful to have. Also, engines could optimize this to always look up the value and then afterwards make the determination on whether to add or remove the value, to save a bunch on branches and code size, resulting in far less overhead.

---

<div class="post-metadata">

**Author:** ![justinfagnani](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/justinfagnani/32/2267_2.png) [@justinfagnani](https://es.discourse.group/u/justinfagnani)\
**Post date:** [October 29, 2024, 5:02pm UTC](https://es.discourse.group/t/set-toggle-method/445/2 "2024-10-29T17:02:28Z")

</div>

I would _love_ to see `.toggle()` added to Set.

I've had a lot of places where I either need a straight toggle (toggle the current value) or a force toggle (set the presence to a computed boolean), and a built-in `.toggle()` would make that code a lot nicer to read.

---

<div class="post-metadata">

**Author:** ![ljharb](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/ljharb/32/8_2.png) [@ljharb](https://es.discourse.group/u/ljharb)\
**Post date:** [October 29, 2024, 10:59pm UTC](https://es.discourse.group/t/set-toggle-method/445/3 "2024-10-29T22:59:00Z")

</div>

what does “toggle the current value” mean for a non-boolean value?

---

<div class="post-metadata">

**Author:** ![justinfagnani](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/justinfagnani/32/2267_2.png) [@justinfagnani](https://es.discourse.group/u/justinfagnani)\
**Post date:** [October 29, 2024, 11:22pm UTC](https://es.discourse.group/t/set-toggle-method/445/4 "2024-10-29T23:22:16Z")

</div>

If the element is present, remove it. If the element is not present, insert it.

---

<div class="post-metadata">

**Author:** ![bakkot](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bakkot/32/22_2.png) [@bakkot](https://es.discourse.group/u/bakkot)\
**Post date:** [October 30, 2024, 2:53am UTC](https://es.discourse.group/t/set-toggle-method/445/5 "2024-10-30T02:53:33Z")

</div>

The basic "toggle" behavior (with no second parameter) is reasonable though I'm not likely to champion it myself.

But for the second parameter, how is "force toggle" any different from `set[include ? 'add' : 'delete'](element)`? I would prefer reading that rather than figuring out what this optional second boolean parameter is doing.

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [November 1, 2024, 2:50am UTC](https://es.discourse.group/t/set-toggle-method/445/6 "2024-11-01T02:50:02Z")

</div>

[DOMTokenList: toggle() method - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/DOMTokenList/toggle) was my cited precedent, and I proposed (near) identical semantics.

> OT: I almost forgot this suggestion even existed. 😅

---

<div class="post-metadata">

**Author:** ![claudiameadows](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/claudiameadows/32/126_2.png) [@claudiameadows](https://es.discourse.group/u/claudiameadows)\
**Post date:** [November 1, 2024, 3:04am UTC](https://es.discourse.group/t/set-toggle-method/445/7 "2024-11-01T03:04:23Z")

</div>

The two-parameter form isn't any different, but from an implementation perspective, both simple toggling and toggling by presence are extremely similar:

```js
Set.prototype.toggle = function (value, force) {
    // The only difference between the two methods
    const forceByExistence = arguments.length < 2

    if (!forceByExistence) force = Boolean(force)

    const location = getEntryLocation(this, value)

    if (forceByExistence) force = !hasValue(location)

    if (force) {
        if (!hasValue(location)) {
            insertAtLocation(this, location, value)
            return false
        } else {
            return true
        }
    } else {
        if (hasValue(location)) {
            removeAtLocation(this, location)
            return true
        } else {
            return false
        }
    }
}

```

(I've implemented a few raw hash tables before. This is basically how they all work.)
