An idea from combination of [...rest, last]
syntax, reverse iterator and function.sent
[first, second, ...rest, last2, last] = o
basically become:
const iter = o[Symbol.Iterator]()
// for backward-compatibility, [x, ...rest] don't test it
if (!iter.canSendMessageToNext) throw new TypeError()
first = iter.next('forward').value
second = iter.next('forward').value
last = iter.next('backward').value
last2 = iter.next('backward').value
let result = iter.next('rest')
if (result.done) {
// allow create `rest` array directly, better perf,
// theoretically could be any iterable,
// but break current codes which expect `rest` always array
// maybe new syntax like `[a, ...rest...] = o` :-)
rest = result.value
} else {
rest = []
for (;;) {
let result = iter.next('forward')
if (result.done) break
rest.push(result.value)
}
}
Array.prototype.values = function *values(array) {
// if contains function.sent, the generator object would have `canSendMessageToNext`
for (let start = 0, end = array.length; start < end;) {
const op = function.sent
if (op === 'rest') return array.slice(start, end)
if (op === 'backward') yield array[--end]
else yield array[start++]
}
}
for reverse (x of it) {...}
just call next("backward")
instead of next()
Iterator.prototype.reverse = function ReverseIterator(this iter) {
if (!iter.canSendMessageToNext) throw new TypeError() // for backward-compatibility
return {
canSendMessageToNext: true,
next(op) {
if (op === 'backward') op = 'forward'
else if (op === 'forward') op = 'backward'
return iter.next(op)
},
}
}
Recent discussion: tc39/proposal-reverseIterator#1 (comment)