Skip to content

Instantly share code, notes, and snippets.

@leobalter
Last active July 25, 2019 22:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leobalter/092fc36adccfcc86e8e7b074817078e1 to your computer and use it in GitHub Desktop.
Save leobalter/092fc36adccfcc86e8e7b074817078e1 to your computer and use it in GitHub Desktop.
// Motivation: we need a reverse iterator for list objects.
// For Arrays, only reduceRight or decrementing loops
// Currently impossible in Map/Set without a full loop or storing the list into an Array
// Goal: a iterator that allows looping through the elements of a list from the last to the first element. Similar to .values()
// Goal: it should not change the original array
// Goal: it should allow interrupting the iteration.
// Question: Should add equivalents to keys and entries?
// Question: Names for the methods?
Symbol.reverse = Symbol('reverseIterator');
function *reverse() {
if (!this || typeof this !== 'object') {
throw new TypeError('this is not an Object');
}
const arr = this;
let { length } = arr;
while (length) {
length = --length;
if (!Object.prototype.hasOwnProperty.call(arr, length)) {
continue;
}
yield arr[length];
// Dynamically jump to the last item in the array if it's shorter
if (arr.length < length) {
length = arr.length; // .next will jump to the latest existing value
}
}
}
Array.prototype[Symbol.reverse] = reverse;
var array1 = [1, 2, 3, 4, 5];
console.log([...array1[Symbol.reverse]()]); // [5, 4, 3, 2, 1];
var obj = {
length: 7,
6: 'a',
get 5() { this.length = 1; return 'b'; },
4: 'z',
1: 'z',
0: 'c'
};
console.log([...Array.prototype[Symbol.reverse].call(obj)]); // [ 'a', 'b', 'c']
var array2 = [1,,2,,,3];
console.log([...array2[Symbol.reverse]()]); // [ 3, 2, 1 ]
/* ------------------- */
// As methods:
Array.prototype.reverseIterator = Array.prototype[Symbol.reverse]; // Needs bikesheding on the name!!!
// Map and Set not drafted here
Map.prototype.reverse = Map.prototype[Symbol.reverse];
Set.prototype.reverse = Set.prototype[Symbol.reverse];
@mhofman
Copy link

mhofman commented Jul 24, 2019

Wondering, why is reverseIterator skipping over gaps when the regular iterator isn't ?

@mathiasbynens
Copy link

Champions, I’d like to request that you please check the entrance criteria and make sure there’s a README section for each item there. For example, “Motivation: we need a reverse iterator for list objects” is not a motivation.

@leobalter
Copy link
Author

This is not the “proposal source” and we plan to write down everything carefully. Please allow us a fair time considering the TC39 meeting is happening this week. I won’t use this motivation, neither rely on this gist only.

@mathiasbynens
Copy link

This is not the “proposal source”

It currently is, though -- this gist is the only thing that the agenda linked to, until the slides (which mostly contain the same info) were added. My point is exactly that: proposals should meet the entrance criteria before asking for stage advancement, and each of the criteria should be addressed in the repository/gist/README.

@ljharb
Copy link

ljharb commented Jul 25, 2019

There is no requirement in the process document for it appearing specifically in any place including the readme; it does say "prose" which means we should indeed document things in writing somewhere, but it seemed a bit obvious since there's tons of usage in the wild of patterns like [...x].reverse() etc, so I don't think it occurred (to me at least) that it would be necessary to spell it out.

Now that it's stage 1, we will of course create a proper proposal repo and document it the conventional way.

(worth noting that this gist also ended up linking to https://github.com/leebyron/ecmascript-reverse-iterable as well which has much more motivation documented)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment