Use Cases
pemrouz opened this issue · 8 comments
As @aklein mentioned, there doesn't seem to be much sense in reversing a Set.
For the other suggested use case, as an iterator prototype method, how would it be possible to have a general .reverse()
? (i.e. you can't buffer all the values since if may be infinite).
Iterators are not generically reversible, so this proposal does not seek to add anything to Iterator.prototype.
This repo seems still empty?
indeed; we haven't updated it yet.
Got some more concrete use cases for reversible iterators: https://es.discourse.group/t/bidirectional-iterators/339
My proposal there is different from this, but anything functionally equivalent to that (like adding a reverse
method) is fine by me.
@isiahmeadows There are some differences in different languages, especially "next_back" (Rust) vs "previous" (Java, Kotlin) vs separate reverse iterator (Clojure and the current state of this proposal ), for example, r = range(1, 5)
:
previous()
(step back)
r.next() // {value:1}
r.next() // {value:2}
r.previous() // {value:1}
r.previous() // {done: true}
r.next() // {value:1}
r.next() // {value:2}
r.next() // {value:3}
r.next() // {value:4}
r.next() // {done:true}
r.next() // {done:true}
r.previous() // {value:4}
next_back()
(shorten range of values from the other end)
r.next() // {value:1}
r.next() // {value:2}
r.next_back() // {value:4}
r.next() // {value:3}
r.next_back() // {done:true}
Your proposal mix the semantics of previous
and next_back
, which seems problematical.
Another important question is how generators could support either of those?
Separate reverse iterator is simple, u just write another generator.
If previous()
or next_back()
, we need a way to retrieve the direction in the generators. A possible way is using the return value of yield
, but we need function.sent
to get the first invoking. An alternative may be introducing a separate function.dir
meta property. Note it is also discussed in Rust, which propose a optional syntax for generators, but I think meta property is the better solution.
Actually, I wrote an idea about that, it use next_back
semantic (though I didn't know Rust DoubleEndedIterator
when I wrote it 😅 ).
@hax It doesn't truncate - it just starts in a different spot. It's otherwise functionally identical to Java's.
Do want to reiterate I'm not beholden to this idea, and I'm still open to alternatives.
I'm interested in joining this conversation. I would like for iter-tools to support reverse iteration. The simplest use case I can think of is making it possible to write an O(1) last(iterable)
method. If anyone is interested there is some prior art in the space, specifically Lee Byron's proposal which is based on the implementation found in Immutable.js.
My personal thought is that the best implementation would be one which does not define any new kind of iterator at all. Not Lee's Symbol.reverseIterator
(or [Symbol.iterator]().reverse()
), nor the more fine-grained iterable[Symbol.iterator]().prev()
. I think the best choice would be to simply create a convention for methods which return normal forward iterables over their contents in the backwards direction. This would be similar to how Map
and Set
offer methods that return iterators, e.g. entries()
. The obvious choice would be to call such a method reverse()
, but of course this is a non-starter since array already has a method with that name. I therefore suggest reversed()
. reversed
describes a way of considering an ordered collection of values (or entries). It feels appropriate to a method which does not have any effect. reverse()
suggests action or change, and indeed this is what the user should expect on calling a reverse()
method.
In such a scenario the only changes to the spec would be adding Array.prototype.reversed
, Map.prototype.reversed
, Set.prototype.reversed
, and perhaps some others that I'm not thinking of.
EDIT: moving this train of thought back the the discussion board as it no longer matches the issue.