Iterables and Generators Flashcards

1
Q

What are Iterables

A

Iterables are objects that have the method
~~~
[Symbol.Iterator]: () => ({
next(): { value: any, done: boolean};
})
~~~

Then methods that iterate work by calling next() until done is true.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

What are generators

A

Generators are special functions that behave differently from regular functions - the body isn’t run when called. Instead, they return a generator object to manage the execution.
The main method of a generator is next(). When called, it runs the execution until the nearest yield and returns { value, done: boolean }

// Simple generator
function* generateSequence(start, end) {
  for (let i = start; i <= end; i++) yield i;
}

//Compound generator
function* generatePasswordCodes() {
  yield* generateSequence(48, 57);
  yield* generateSequence(65, 90);
  yield* generateSequence(97, 122);
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

What’s the output of the following code?

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

for(let value of generator) {
  alert(value);
}
A

1,2

Generators return an object that is compatible with Iterator method, so they can be iterated over.
However only yield statements are considered, so return 3 is not included.

Since generator functions are essentially the same as Iterator, the following objects are equivalent:

// First object
let range = {
from: 1,
to: 5,

Symbol.iterator {
return {
current: this.from,
last: this.to,

  next() {
    if (this.current <= this.last) {
      return { done: false, value: this.current++ };
    } else {
      return { done: true };
    }
  }
};   } };

// Second object
let range = {
from: 1,
to: 5,

*Symbol.iterator {
for(let value = this.from; value <= this.to; value++) {
yield value;
}
}
};

alert( […range] ); // 1,2,3,4,5

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

What is the output of the following code?

function* gen() {
  // Pass a question to the outer code and wait for an answer
  let result = yield "2 + 2 = ?"; // (*)

  alert(result);
}

let generator = gen();

let question = generator.next().value; //(1)
const answer = prompt(question, 4);
generator.next(answer); //(2)
A

4

‘yield’ is a two way street, is not only produces data(since its value is included in generator object), it can also consume data as it acts a placeholder for receiving any data if .next() is called with a value.

So:
At (1), next() is called which goes to the nearest yield statement and returns { value: “2+2 = ?”, done: false } and pauses.
At (2), we call next(4), and since we left of at (*), result is assigned to 4, and 4 is alerted.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

What are async iterables?

A

Async Iterables are objects that have the method

[Symbol.asyncIterator]: () =>({
  async next(): Promise;
})

Then you can loop using for await(const .. of)

Note since [Symbol.asyncIterator] !== [Symbol.Iterator], methods like spreading are not available.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What are async generators

A

Async generators return a generator object { async next(): Promise }

async function* generateSequence(start, end) {

  for (let i = start; i <= end; i++) {

    // Wow, can use await!
    await new Promise(resolve => setTimeout(resolve, 1000));

    yield i;
  }
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly