Is it possible to define an array iterator that adjusts to your for-of syntax?

# Šime Vidas (9 years ago)

Say I have an array over which I need to iterate multiple times, but I need the index value only some of the time. Is it possible to create a custom iterator which auto-detects when I need the index and feeds me entries() instead of values() in those cases? For example:

array[Symbol.iterator] = /* some magic here */

for (let elem of array) { /* values() iterator is used automatically / } for (let [i, elem] of array) { / entries() iterator is used automatically */ }

# Logan Smyth (9 years ago)

It is not possible to detect this.

for (let [i, elem] of arr){

is no different that than

for (let pair of arr){
  let [i, elem] = pair;

You are destructuring the result of an iterator, and the initialization of the iterator is independent from the initialization of the destructuring pattern.

# Allen Wirfs-Brock (9 years ago)

On May 22, 2016, at 1:55 PM, Šime Vidas <sime.vidas at gmail.com> wrote:

Say I have an array over which I need to iterate multiple times, but I need the index value only some of the time. Is it possible to create a custom iterator which auto-detects when I need the index and feeds me entries() instead of values() in those cases? For example:

array[Symbol.iterator] = /* some magic here */

for (let elem of array) { /* values() iterator is used automatically / } for (let [i, elem] of array) { / entries() iterator is used automatically */ }

The ES internal protocol design assumes that you would to this as follows:

for (let elem of array.entries()) { /* values() iterator is explicitly used / } for (let [i, elem] of array.elements()) { / entries() iterator is explicitly used */ }

No magic is necessary.

# Jason Orendorff (9 years ago)

No, it's not possible.

Oddly enough, when this functionality was first prototyped in SpiderMonkey many years ago, the iterator protocol did pass a boolean to the iterator method (this was before symbols) based on the syntax you were using to unpack the results. This feature was not super useful in practice, and I always thought it was too subtle -- the difference in syntax was really not explicit enough to make it clear to the programmer what was going on. I'm glad it wasn't standardized.

# Renki Ivanko (9 years ago)

There could be a protocol for defining the shape of the iterator's returns, but it would need to use functions instead of the loop syntax. I've previously suggested something like:

iterator[Symbol.shape] = Symbol.shape.entries

Then a generic iteration function supporting this interface would know that the iterator returns entries (key/value pairs) and pass them as separate parameters to the callback. Something like:

map(iterator, (key, value) => ...)

The benefit of this is kind of trivial, though, since all you save yourself from doing is writing ([key, value]) for the callback function parameters.

R. untu.ms