Skip to content

Instantly share code, notes, and snippets.

@juanmaguitar
Last active September 29, 2016 19:25
Show Gist options
  • Save juanmaguitar/61a6b741fb05519b42b198d0ff182c1c to your computer and use it in GitHub Desktop.
Save juanmaguitar/61a6b741fb05519b42b198d0ff182c1c to your computer and use it in GitHub Desktop.
generators examples
/* ------------------------------------------------------- */
/* GENERATORS USING PREV VALUES */
/* ------------------------------------------------------- */
function *foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var it = foo( 5 );
console.log( it.next() ); // { value:6, done:false }
console.log( it.next( 12 ) ); // { value:8, done:false }
console.log( it.next( 13 ) ); // { value:42, done:true }
/* ------------------------------------------------------- */
/* INFINITE GENERATORS */
/* ------------------------------------------------------- */
var nat = function*() {
var i = 0;
while(true) {
yield ++i;
}
};
/* ------------------------------------------------------- */
/* HIGHER ORDER FUNCTIONS */
/* ------------------------------------------------------- */
var map = function* (fn, genFn) {
var genObj = genFn();
var current = genObj.next();
while(!current.done) {
yield fn(current.value);
current = genObj.next();
}
return fn(current.value);
};
var double = function(x) { return 2*x; }
var even = map(double, nat);
console.log(even.next()); // Object {value: 2, done: false}
console.log(even.next()); // Object {value: 4, done: false}
/* ------------------------------------------------------- */
/* ITERATING GENERATORS */
/* ------------------------------------------------------- */
var upto = function(limit) {
return function*() {
var i = 0;
while(i < limit) {
yield i++;
}
return limit;
};
};
var serie = [];
for(var current of upto(3)() ) {
serie.push(current);
}
console.log( serie.join(" - ") ) // 0 - 1 - 2
/* ------------------------------------------------------- */
/* CONSTANT */
/* ------------------------------------------------------- */
var constant = function*(value) {
while(true) {
value = (yield value) || value;
}
};
var five = constant(5);
console.log(five.next().value); // 5
console.log(five.next().value); // 5
console.log(five.next(6).value); // 6
console.log(five.next().value); // 6
/* ------------------------------------------------------- */
/* ASYNC OPERATIONS W/ GENERATORS */
/* ------------------------------------------------------- */
var fs = require('fs');
var co = require('co');
co(function*(){
var content = yield fs.readFile('code/a.txt', 'utf8');
console.log(content);
})();
/* SIMPLERCO */
var simplerCo = function(gen) {
var genObj = gen();
var currentValue = genObj.next();
currentValue.value(function(err,data) {
genObj.next(data);
});
};
/* USING SIMPLERCO */
var fs = require('fs');
var readFile = function() {
var args = Array.prototype.slice.call(arguments,0);
return function(callback) {
args.push(callback);
return fs.readFile.apply(null, args);
};
};
simplerCo(function*() {
var content = yield readFile('code/a.txt', 'utf8');
console.log(content);
});
/* ------------------------------------------------------- */
/* HANDLING ERRORS */
/* ------------------------------------------------------- */
function *foo() {
try {
var x = yield 3;
console.log( "x: " + x ); // may never get here!
}
catch (err) {
console.log( "Error: " + err );
}
}
var it = foo();
console.log ( it.next() ) ; // { value:3, done:false }
it.throw( "Oops!" ); // Error: Oops!
// {value: undefined, done: true}
// ----
function *foo() { }
var it = foo();
try {
it.throw( "Oops!" );
}
catch (err) {
console.log( "Error: " + err ); // Error: Oops!
}
// --------------------------------------
function *foo() {
var x = yield 3;
var y = x.toUpperCase(); // could be a TypeError error!
yield y;
}
var it = foo();
it.next(); // { value:3, done:false }
try {
it.next( 42 ); // `42` won't have `toUpperCase()`
}
catch (err) {
console.log( err ); // TypeError (from `toUpperCase()` call)
}
/* ------------------------------------------------------- */
/* DELEGATE GENERATORS */
/* ------------------------------------------------------- */
function *foo() {
yield 3;
yield 4;
}
function *bar() {
yield 1;
yield 2;
yield *foo(); // `yield *` delegates iteration control to `foo()`
yield 5;
}
for (var v of bar()) {
console.log( v );
}
// 1 2 3 4 5
// ----------------------
function *foo() {
var z = yield 3;
var w = yield 4;
console.log( "z: " + z + ", w: " + w );
}
function *bar() {
var x = yield 1;
var y = yield 2;
yield *foo(); // `yield*` delegates iteration control to `foo()`
var v = yield 5;
console.log( "x: " + x + ", y: " + y + ", v: " + v );
}
var it = bar();
it.next(); // { value:1, done:false }
it.next( "X" ); // { value:2, done:false }
it.next( "Y" ); // { value:3, done:false }
it.next( "Z" ); // { value:4, done:false }
it.next( "W" ); // { value:5, done:false }
// z: Z, w: W
it.next( "V" ); // { value:undefined, done:true }
// x: X, y: Y, v: V
/* ------------------------------------------------------- */
/* SIMPLEST ASYNC */
/* ------------------------------------------------------- */
// ----> from this....
function makeAjaxCall(url,cb) {
// do some ajax fun
// call `cb(result)` when complete
}
makeAjaxCall( "http://some.url.1", function(result1){
var data = JSON.parse( result1 );
makeAjaxCall( "http://some.url.2/?id=" + data.id, function(result2){
var resp = JSON.parse( result2 );
console.log( "The value you asked for: " + resp.value );
});
} );
// ----> to this....
function request(url) {
// this is where we're hiding the asynchronicity,
// away from the main code of our generator
// `it.next(..)` is the generator's iterator-resume
// call
makeAjaxCall( url, function(response){
it.next( response );
} );
// Note: nothing returned here!
}
function *main() {
var result1 = yield request( "http://some.url.1" );
var data = JSON.parse( result1 );
var result2 = yield request( "http://some.url.2?id=" + data.id );
var resp = JSON.parse( result2 );
console.log( "The value you asked for: " + resp.value );
}
var it = main();
it.next(); // get it all started
/* ------------------------------------------------------- */
/* ASYNC EXAMPLE */
/* ------------------------------------------------------- */
var login = async(function* (username, password, session) {
var user = yield getUser(username);
var hash = yield crypto.hashAsync(password + user.salt);
if (user.hash !== hash) {
throw new Error('Incorrect password');
}
session.setUser(user);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment