Sample Iterator and Generator

JavaScript

/*
process.run([1,2,3,4]);*/
'use strict';

const natural = function*() {
  let i = 1;
  while (true) yield i++;
}

const mylist = {
  [Symbol.iterator]() {
    return {
      next() {
        console.log('next called');
        if (this.count == null)
          this.count = 4;
        if (this.count-- > 0)
          return {
            value: this.count,
            done: false
          };
        return {
          value: undefined,
          done: true
        };
      }
    }
  }
};

learn('spread operator should call the iterator on object', ()=>{
	console.log(...mylist)
})

learn('Generators return themselves as their iterator', ()=>{
  const nat = natural();
  // generators are wired in a way to automatically return themselves as iterators
  console.log(nat[Symbol.iterator]() == nat);
  console.log(nat.next);
})


function* greet() {
  try {
    console.log('started generator')
    console.log(`hello ${yield 'started'}`);
    console.log('stopped generator')
  } catch (e) {
    console.log('Error', e);
  } finally {
    console.log('finally!');
  }
}

learn('What are the steps of running a generator?', ()=>{
  const greeter = greet();
  console.log('calling first next');
  console.log(greeter.next('test'));
  console.log('calling second next');
  console.log(greeter.next('second'));
  console.log('after second next');

  console.log('------------------------');
});

const newGreeter = greet();
newGreeter.next();
if (newGreeter.return)
  newGreeter.return('third');
else
  console.error('Browser does not support return function on iterators');

newGreeter.throw({
  error: 'bad'
});

function* map(iterable, mapFunc) {
  for (let x of iterable) {
    yield mapFunc(x);
  }
}

function* take(iteratable, count) {
  let gen = 0;
  for (let val of iteratable) {
    if (gen++ < count)
      yield val;
    else
      return;
  }
}

function* filter(iterable, condition) {
  for (let val of iterable) {
    if (condition(val))
      yield val;
 ...