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];
@hax
Copy link

hax commented Jul 6, 2019

  1. Will you like to add something like for ... of reverse ... syntax?

  2. Array.prototype.reverse() will mutate the original array. So maybe we should use other name?

@MaxGraey
Copy link

MaxGraey commented Jul 6, 2019

Hmm, interesting. What about add new reversed spread syntax?

const arr = [1,2,,3]
console.log([...arr]); // [ 1, 2, 3 ]
console.log([arr...]); // [ 3, 2, 1 ]

Second suggestion is use reversed instead reverse:

Array.prototype.reversed = Array.prototype[Symbol.reversed];
Map.prototype.reversed = Map.prototype[Symbol.reversed];
Set.prototype.reversed = Set.prototype[Symbol.reversed];

@domenic
Copy link

domenic commented Jul 6, 2019

Please see https://github.com/leebyron/ecmascript-reverse-iterable for previous work in this area. Contemporary meeting notes probably have good discussions.

@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