Mflow
Mflow is the monad-style flow control library for nodejs.
This library is inspired by followings:
Supported monad-style flows are followings:
Caution
Mflow uses ECMAScript 6 generators.
Currently you must use the --harmony-generators
flag when running node 0.11.x.
Installation
$ npm install mflow
Example
This is an async flow.
var fs = require('fs');
var mflow = require('mflow');
var async = mflow.async;
var flow = async(function *() {
var a = yield function(f) { fs.readFile('file1', 'utf8', f); };
var b = yield function(f) { fs.readFile('file2', 'utf8', f); };
return a + b;
});
flow(function (err, data) {
if (err) throw err;
console.log(data);
});
API
Mflow provides following top-level functions:
These functions accept a generator function which has no parameter.
async(fn)
Makes an async flow.
fn
: a generator function- return: an async function
The yieldable values are followings:
- a function which has one parameter and passes it to an async function
- an async flow
yield
returns the async function's result.
var fs = require('fs');
var mflow = require('mflow');
var async = mflow.async;
var flow = async(function *() {
var a = yield function(f) { fs.readFile('file1', 'utf8', f); };
var b = yield function(f) { fs.readFile('file2', 'utf8', f); };
return a + b;
});
flow(function (err, data) {
if (err) throw err;
console.log(data);
});
async.join(fn...)
Runs multiple async functions in parallel.
fn...
: multiple functions or an array of function- return: a yieldable function. When this function is yielded, all joined function's results are returned as an array.
var fs = require('fs');
var mflow = require('mflow');
var async = mflow.async;
var flow = async(function *() {
var a = function(f) { fs.readFile('file1', 'utf8', f); };
var b = function(f) { fs.readFile('file2', 'utf8', f); };
var results = yield async.join(a, b);
return results[0] + results[1];
});
flow(function (err, data) {
if (err) throw err;
console.log(data);
});
lazy(fn)
Makes a lazy flow.
fn
: a generator function- return: a function which wraps an expression. When this function is called or is yielded, the expression is evaluated only once.
The yieldable values are followings:
- a function which has no parameter and returns a value
- a lazy flow
- non-function value: When it is yielded, the value is returned without any change.
var mflow = require('mflow');
var lazy = mflow.lazy;
var x = 10;
var result = lazy(function *() {
return x + 10;
});
console.log(result());
When a non-function value is yielded, the value is returned without any change.
var mflow = require('mflow');
var lazy = mflow.lazy;
var x = 10;
var lazyValue1 = lazy(function *() { return x + 10; });
var lazyValue2 = lazy(function *() { return x * 10; });
function add(value1, value2) {
return lazy(function *() {
var a = yield value1;
var b = yield value2;
return a + b;
});
};
console.log(add(lazyValue1, lazyValue2));
console.log(add(1, 2));
maybe(fn)
Runs a flow which results a successful value or null
.
fn
: a generator function- return: a successful value or
null
The yieldable values are followings:
null
undefined
- other values
When null
or undefined
is yielded, the flow is stopped and results null
.
Otherwise the yielded value is returned without any change.
var mflow = require('mflow');
var maybe = mflow.maybe;
function add(x, y) {
return maybe(function *() {
var a = yield x;
var b = yield y;
return a + b;
});
}
console.log(add(1, 2));
console.log(add(1, null));
state(fn)
Makes a state flow.
fn
: a generator function- return: a function which has one parameter and returns an array.
The parameter is a flow's state. The returned array contains the flow's result as 1st elment and the flow's state as 2nd element.
The yieldable values are followings:
- a function which has one parameter and returns an array.
The parameter is a flow's state. The returned array contains the flow's result as 1st elment and the flow's state as 2nd element.
- a state flow
var mflow = require('mflow');
var state = mflow.state;
function pop() {
return function (s) {
return [s.shift(), s];
};
}
function push(value) {
return function (s) {
s.unshift(value);
return [null, s];
};
}
var flow = state(function* () {
var a = yield pop();
if (a === 5) {
yield push(5);
} else {
yield push(3);
yield push(8);
}
return 10;
});
var result = flow([9, 0, 2, 1, 0]);
console.log(result[0]);
console.log(result[1]);
state.get()
Gets a flow's state.
- return: a yieldable function. When this function is apply to
yield
, a flow's state are returned.
pop
and push
functions in abobe code can be replaced with following implementations using state.get
and state.put
:
var pop = function () {
return state(function *() {
var s = yield state.get();
var ret = s.shift();
yield state.put(s);
return ret;
});
};
var push = function (value) {
return state(function *() {
var s = yield state.get();
s.unshift(value);
yield state.put(s);
});
};
state.put(s)
Puts a new state as a flow's state.
s
: a new state- return: a yieldable function. When this function is apply to
yield
, a flow's state is replaced with the argument.
See state.get()
.
state.eval(flow, s)
Runs a flow and returns the flow's result.
flow
: a state flows
: a flow's state
Followings are equivalent:
var result = state.eval(flow, [9, 0, 2, 1, 0]);
console.log(result);
var result = flow([9, 0, 2, 1, 0]);
console.log(result[0]);
state.exec(flow, s)
Runs a flow and returns the flow's state.
flow
: a state flows
: a flow's state
Followings are equivalent:
var result = state.exec(flow, [9, 0, 2, 1, 0]);
console.log(result);
var result = flow([9, 0, 2, 1, 0]);
console.log(result[1]);
Test
$ mocha --harmony-generators
License
MIT