With doing an iterator/Generator in javascript?

Asked

Viewed 439 times

8

In PHP, we have the Iterators and the Generator.

Iterator example:

$f = new FileSystemIterator(__DIR__);

foreach($f as $file) {
    echo $file->getFilename();
}

Example Generator:

function sequence($start, $end) {
    for ($i = $start; $i <= $end; ++$i) {
       yield $i;
    }
}

foreach(sequence(1, 10) as $value) {
     echo $value;
}

// Imprime: 12345678910

I find the use of both very interesting, especially when it comes to Iterator iterating over a list of objects.

Is there any way to create a Iterator or Generator in Javascript? And if not, is there any way to simulate them?

  • You kept thinking about the Iterators who wrote essential. KKKKKK

  • @Deesouza, it’s true! kkkkkk. Corrected :|

  • ES6 Valley? There they are natively supported.

  • yes, vale. Remember that question? http://answall.com/questions/90290/existe-alguma-forma-de-estender-um-objeto-em-javascript

  • Okay, because then we get the news :)

1 answer

8


The specification Ecmascript 6 added Iterators and generators to the hard core of language, but today (end of 2015) there is still limitations of browser support. I will explain how it works/will work, so that we are already prepared for the future :)

Iterators

A iterator in ES6 is simply an object that implements a method next, responsible for returning the next item of the sequence - an object with the properties done and value. There is no new syntax, what was created is simply a protocol. Example of MDN:

function makeIterator(array){
    var nextIndex = 0;

    return {
       next: function(){
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    }
}

var it = makeIterator(['yo', 'ya']);
console.log(it.next().value); // 'yo'
console.log(it.next().value); // 'ya'
console.log(it.next().done);  // true

http://www.es6fiddle.net/ifjmbbko/

In PHP, a iterator may be listed by a foreach, because he’s also Enumerable. In ES6 there is the for..of, but he does not list Iterators, and yes iterables, that are objects that implement @@iterator - that is, they have a key method Symbol.iterator. This method returns a iterator:

function makeIterable(array){

    var nextIndex = 0;
    var it = {};
    it[Symbol.iterator] = function() {
        return {
            next: function(){
                return nextIndex < array.length ?
                       {value: array[nextIndex++], done: false} :
                       {done: true};
            } 
        };
    };
    return it;
}

for(let val of makeIterable(['yo', 'ya'])) console.log(val);

http://www.es6fiddle.net/ifjolmy6/

The most practical way to create a iterable is to use a generating function (which we will discuss later on):

var myIterable = {}
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};

for(let val of myIterable) {
    console.log(val) 
}

http://www.es6fiddle.net/ifjnkxb4/

A iterator may also be iterable, which is closer to what happens in PHP:

function makeIterableIterator(array){

    var nextIndex = 0;
    var it = {};
    it[Symbol.iterator] = function() {
        return this;
    };
    it.next = function(){
        return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
    };

    return it;
}

for(let val of makeIterableIterator(['yo', 'ya'])) console.log(val);

http://www.es6fiddle.net/ifjox839/

That’s kind of what the iterables which are part of the core of language, such as Array, Map, Set etc..

To learn more about iterables, recommend reading Iterables and Iterators in Ecmascript 6, where there are many examples.

Generators

The generating functions facilitate the creation of iterables. They are basically functions with the ability to suspend their execution, and yet maintain the status for the next execution. ES6 introduced a new syntax for this, function*. Simple example of MDN:

function* idMaker(){
  var index = 0;
  while(true)
    yield index++;
}

var gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2

http://www.es6fiddle.net/ifjpkcxq/

The generator created by idMaker is at the same time a iterator and a iterable. The "magic" is on account of yield, that is who suspends the execution. Each time the next is executed, the function resumes where it left off, with its local scope intact.

Basically, generators allow the creation of computed sequences in a "lazy" way, one value at a time, as the values are needed. They can also be combined with promises so that it is possible to treat asynchronous operations in a similar way, can be chained recursively, and can be exchange data among themselves, allowing the implementation of co-routines.

  • You can go far on this topic. I decided to stop here so as not to get too big or run away from what was asked.

  • Good! +1 this opens an interesting door to very interesting asynchronous processes.

  • Fiddle links are no longer working

Browser other questions tagged

You are not signed in. Login or sign up in order to post.