Last active
September 29, 2016 19:25
-
-
Save juanmaguitar/61a6b741fb05519b42b198d0ff182c1c to your computer and use it in GitHub Desktop.
generators examples
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* ------------------------------------------------------- */ | |
| /* 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