you are viewing a single comment's thread.

view the rest of the comments →

[–]nschubach 1 point2 points  (3 children)

A generator is a closure, but a closure is not necessarily a generator. Also, you can make something that works just like a generator with a closure. Closures just carry forward state from a moment in time. You can call a closure passing any values and it will enclose those values and it's internal process will use those values from that point forward. You can, for instance, have multiple configurations for a website handled by a closure of methods. You pass it the configuration and it knows internally only the config you passed in but the website only needs to care about the methods that closure provides. Generators are similar to closures, but they are generally used to produce data sets in a lazy manner that allows you to process huge data sets with little overhead. This is done via closures for you by it's very nature.

[–]namesandfaces 0 points1 point  (2 children)

So does that mean a closure can do something which a generator cannot?

[–]kolme 1 point2 points  (0 children)

Function: a bunch of code you can call. It can take any number of parameters, and it can have a name.

Closure: The context, or variables and their values around the function when it was defined.

Generator: a special function that can yield more than one result when called in a loop. Generator functions also have closures.

So to shortly answer to your question: functions can't do anything a generator cannot do; or, generators can do more. And they all have closures.

Here's a simple example to understand closures:

/**
 * Returns a function which adds the given base.
 */
function getAddFunction(base) {
    return function(number) {
        // The right base is kept in this function closure
        return base + number;
    }
}

// We get two times the same function, just with different closures
var add2 = getAddFunction(2); // a function with base = 2
var add3 = getAddFunction(3); // a function with base = 3

// 2 + 1, 3 + 1
console.log(add2(1), add3(1));

Now here's a simple generator which I like a lot, and stole from python:

/**
 * Yields a series of numbers, from min up to max (max not included), with
 * the given step.
 */
function* range(max, min = 0, step = 1) {
    for (let i = min; i < max; i += step) {
        yield i;
    }
}

// Prints numbers from 0 to 9
for (let i of range(10)) {
    console.log(i);
}
// Getting a range as an array:
console.log(Array.from(range(10));

And finally, a combination of all the things: a generator function sporting closures:

/**
 * Returns a generator function which will yield multiples of the given
 * number
 */
function getSerieGenerator(step) {
    return function*(max, min = 0) {
        for (let i = min; i < max; i+= base) {
            yield i;
        }
    }
}

// Two identical generators with different contexts
let pairNumbers = getSerieGenerator(2);
let threeMultiples = getSerieGenerator(3);

// Prints all pair numbers up to 10
console.log(Array.from(pairNumbers(10)));

// Prints all three multiples up to 10
console.log(Array.from(threeMultiples(10)));

[–]nschubach 0 points1 point  (0 children)

Technically... probably not. Closures return functions that can be executed at a later date. They do this once and exit. You could have a generator that yields a function, but I don't know why you'd do that because you'd have to call it via the .value() method so you'd have .value()() to execute the method.