# Array.prototype.reversed() (+Map, Set)

**URL:** <https://es.discourse.group/t/array-prototype-reversed-map-set/556>\
**Category:** 💡 Ideas\
**Created:** [November 22, 2020, 8:07pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556 "2020-11-22T20:07:43Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 22, 2020, 8:07pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/1 "2020-11-22T20:07:43Z")

</div>

I'm offering this as a competitor to existing proposals for bidirectional or reverse iteration, namely [Bidirectional iterators](https://es.discourse.group/t/bidirectional-iterators/339) and [https://github.com/leebyron/ecmascript-reverse-iterable](https://github.com/leebyron/ecmascript-reverse-iterable).

The idea is to create `Array.prototype.reversed`, as well as `Map.prototype.reversed` and `Set.prototype.reversed` methods.

Usage would look like this:

```javascript
for (const value of values.reversed()) {
}

```

What I see as the advantages:

- Very easy to specify and implement.
- It is clear that once iteration is started it can proceed in only one direction.
- All existing tooling for working with iterators still functions as intended. There's nothing new it needs to know about.
- There are no runtime errors to worry about. With a system that describes a generic approach to reverse iteration a new common error will be "Reverse iteration is not implemented".
- With no (new) runtime errors it will be possible with existing static analysis tools to verify that code will not throw an error. If a `reversed()` method is not present: a type system warns you. If a `reversed()` method is present but its return value is not iterable: a type system warns you.
- Speaking of type systems, there is no base class for Iterators. For typescript this means that when you write `Iterable<T>` you're just declaring that an iterator's `next()` method should return an object of type `{ done: boolean, value: T }`. Adding a `previous()` method complicates the type checking. What if for some reason the types returned by the `previous()` and `next()` methods conflict? It shouldn't happen, but it probably would and the resultant error would be highly cryptic.
- Finally it offers myriad syntactic options. Obviously it would be best to choose a single convention to follow, but all of the following would be possible: `myMap.keys().reversed()`, `myMap.keys.reversed()` or just `myMap.keysReversed()` method. Authors of libraries would be free to chose the most sensible syntax for their use cases.

---

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 22, 2020, 9:01pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/2 "2020-11-22T21:01:21Z")

</div>

Also by avoiding creating additional mechanisms it ensures that additional work is not needed to support reverse iterator of async iterables. You would simply write `reversed: () => ({ [Symbol.iterator](): { ... }, [Symbol.asyncIterator](): { ... } })`.

If my other proposal for `Symbol.syncAndAsyncIterator` were to be accepted those too would work without additional effort.

---

<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 23, 2020, 2:52am UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/3 "2020-11-23T02:52:50Z")

</div>

I like the idea, but it doesn't make sense to include it for maps and sets.

Better would be just tacking it onto the iterable protocol as an optional member: [https://github.com/leebyron/ecmascript-reverse-iterable/issues/5](https://github.com/leebyron/ecmascript-reverse-iterable/issues/5)

---

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 23, 2020, 3:02am UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/4 "2020-11-23T03:02:51Z")

</div>

The iterable protocol consists of a single symbol, `Symbol.iterator` (returning an iterator). I don't see that it's possible to add anything to the iterable protocol. You could add it to the iterator protocol of course, but the iterator protocol in my mind is an implementation detail which the vast majority of the time should be hidden away behind higher level constructs.

---

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 23, 2020, 3:41am UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/5 "2020-11-23T03:41:33Z")

</div>

My bigger concern really is that the algorithm for taking an arbitrary IterableIterator and reversing it is already perfectly well supported in javascript, because it is `[...iter].reverse()`. As soon as you do any operation on the iterable, such as slicing it, it is no longer possible to reverse without that array allocation. This is because reversing a slice of an array is not the same operation as slicing the reverse of an array. So if reversing is only really possible as an operation on allocated objects (like arrays), then why would you define it as an operation on iterators?

---

<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 23, 2020, 4:22am UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/7 "2020-11-23T04:22:22Z")

</div>

This is very much _not_ how Immutable's reversed lists as referenced in that issue are implemented. They elide the reversal entirely. And iterables can themselves be iterators, as is the case with generator instances.

So no, those concerns do not hold with my suggestion there.

---

<div class="post-metadata">

**Author:** ![bergus](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/bergus/32/152_2.png) [@bergus](https://es.discourse.group/u/bergus)\
**Post date:** [November 23, 2020, 1:42pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/8 "2020-11-23T13:42:57Z")

</div>

I don't see how this is so different from Lee Bryon's proposal. Yes, you're creating a `reverse()` method on each iterator kind instead of shared `reverse()` method that goes to call a symbol-keyed method, but the end result is exactly the same.

> [@conartist6](#):
>
> It offers myriad syntactic options. Obviously it would be best to choose a single convention to follow, but all of the following would be possible: `myMap.keys().reversed()`, `myMap.keys.reversed()` or just `myMap.keysReversed()` method

The first would require a `reversed` method on the `ArrayIteratorPrototype`/`MapIteratorPrototype`/etc objects, which you seemed to reject initially? The second is not actually possible. The third would mean having to create three methods `reversedKeys()`/`reversedValues()`/`reversedEntries()` on all collection prototypes, which is quite some overhead.

I would suggest instead of considering this a "competitor" to the existing proposal, you open an issue there and propose a simplification by removing "The _ReverseIterable_ Interface" and having simple `reverse()` methods on iterators instead of implementing a symbol protocol that's not used by any syntax.

---

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 23, 2020, 2:26pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/9 "2020-11-23T14:26:22Z")

</div>

Yeah I really don't like `keys().reversed()` for all the reasons I just laid out, and we can rule out anything that's not possible. I guess I think the benefits makes it worth some cost.

As for Lee's proposal, I consider it dead. In particular it is based on immutable.js, which is itself seemingly dead to Lee. I spent two years trying to poke and prod him into giving the project some of the attention it needs, but recently I forked it and members of the community have taken over support and new development. I will not tie any more of my prospects to him. He's within his rights to shift his focus to new projects and his job and his life, and I think I'm within my rights to compete with him instead of trying to follow him around everywhere.

---

<div class="post-metadata">

**Author:** ![conartist6](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/conartist6/32/515_2.png) [@conartist6](https://es.discourse.group/u/conartist6)\
**Post date:** [November 23, 2020, 2:37pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/10 "2020-11-23T14:37:36Z")

</div>

Sorry @claudiameadows, I misunderstood.

---

<div class="post-metadata">

**Author:** ![septs](https://yyz2.discourse-cdn.com/free1/user_avatar/es.discourse.group/septs/32/395_2.png) [@septs](https://es.discourse.group/u/septs)\
**Post date:** [November 24, 2020, 3:25pm UTC](https://es.discourse.group/t/array-prototype-reversed-map-set/556/11 "2020-11-24T15:25:22Z")

</div>

CC @hax @Kingwl
