Skip to content

Instantly share code, notes, and snippets.

@19h
Last active August 29, 2015 14:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 19h/06a8fecf4428b9b6406c to your computer and use it in GitHub Desktop.
Save 19h/06a8fecf4428b9b6406c to your computer and use it in GitHub Desktop.
Node.js Professionals Alliance Berlin #1 Meetup: Generators
var Foo = function * (c) {
var a = [0, 1],
b = 0;
for (b = 0; b < c; ++b) {
a.push(a[0] + a[1]);
a.shift();
yield a[a.length - 1];
}
return a[0]
}
// initialize generator
var foo = Foo(12);
// kick off generator
var a = foo.next(); // { value: 1, done: false }
// using for .. of
for ( var a of foo ) {
console.log(a);
/*
2
3
5
8
13
21
34
55
89
144
233
*/
}
/*
^^^^^^^^^^^^^^^^
for .. of will directly use "value" of the result,
BUT you won't be able to pass a parameter to .next
nor will you be able to .throw from the iterator.
*/
// Math example
var FooMath = function * (){
var a = 0;
for(;;) {
a = yield a;
++a;
}
}
/*
The first .next will yield 0 (a) and when passed a value,
the passed value will substitute the expression and resume
at that exact location. Let's mutate "a".
*/
var fooMath = FooMath();
fooMath.next(); // { value: 0, done: false }
fooMath.next(100); // { value: 101, done: false }
// Hypothetical use in an application
/*
We have a generator that obtains user data;
we will inspect the return values and inject
the info that is asked for by using .next
and will throw errors in the generator-scope
by using the .throw method.
*/
var db = {
"kenansulayman": {
name: "Kenan Sulayman",
job: "Software Architect"
},
"homerdong": {
name: "Homer Dong",
job: "PHP veteran"
}
}
var fooGetVal = function * (id){
// user id is "id"
var user = {
id: id
}
try {
user.name = yield {
type: "name",
id: id
};
} catch(e) {
if ( e === "No such id" ) {
return yield {
type: "result",
data: null
};
}
}
yield {
type: "result",
data: user
};
}
// this will usually be in a loop:
var reaper = function (cb, myGetVal, param) {
var retval = myGetVal.next(param).value; // { type: "name", id: "kenansulayman" }
if ( retval.type === "name" ) {
if ( db[retval.id] ) {
param = db[retval.id].name;
} else {
myGetVal.throw("No such id");
return cb(null);
}
}
if ( retval.type === "result" ) {
return cb(retval.data);
}
return reaper(cb, myGetVal, param)
};
var myGetVal = fooGetVal("kenansulayman");
reaper(function (user) {
console.log(user); // { id: 'kenansulayman', name: 'Kenan Sulayman' }
}, myGetVal);
var myGetVal2 = fooGetVal("homerdong");
reaper(function (user) {
console.log(user); // { id: 'homerdong', name: 'Homer Dong' }
}, myGetVal2);
var myGetVal3 = fooGetVal("peter");
reaper(function (user) {
console.log(user); // "null"; see line 32 - 35
}, myGetVal3);
var foo = function * () {
var a = 10;
while (a--) yield a;
}
var foo2 = function * () {
var a = 10;
yield* foo(); // delegate to foo^
while (a--) yield Math.random();
}
for ( var a of foo2() ) {
console.log(a)
}
// Example output
/*
9
8
7
6
5
4
3
2
1
0
0.31441035214811563
0.932482686592266
0.49652760615572333
0.5199203079100698
0.7944680366199464
0.21947496198117733
0.7085313643328846
0.11945359944365919
0.20332212862558663
0.15203028940595686
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment