FRP(Functional reactive programming) supporting DSL. Lazy stream, monad, pattern match, guard implements in JavaScript.
Data-Oriented Design by Pipeline
mainstream
[input]
| substream(async)
| ----> |
| : procstream
| | ----> |
| | |
| | <---- |
| |
| | ajax(async)
| | ----> |
| | :
| | <---- |
| |
| | worker(async)
| | ----> |
| | :
| | <---- |
| |
| | process
| | ----> |
| | |
| | <---- |
| |
| <---- |
|
[output]
var streams = build({
main: LazyChain(),
sub: LazyChain(),
proc: LazyChain()
});
streams.main.notify('');
function build(streams) {
streams.proc
.map(encodeURI);
streams.sub
.lazy()
.stream(streams.proc)
.lazy(req)
.filter(isXHR)
.map(conv);
streams.main
.stream(streams.sub)
.stream(alert);
return streams;
}
function req(v) {
return $.ajax(v);
}
function isXHR(v) {
return v instanceof Object;
}
function conv(xhr) {
return xhr.responseText;
}
// Double dispatch by pattern match
class A {
constructor(public val?) {
}
type = 1
}
class B {
constructor(public val?) {
}
type = 2
}
var f = LazyChain.dispatcher<A|B, string>([
[<A|B>{ val: 0 }],
_ => 'val 0'
], [
[<A|B>{ val: Number }],
_ => 'val Number'
], [
[A],
_ => 'A'
], [
[<B>{ type: 2 }],
_ => 'type 2'
], [
[B],
_ => 'B'
]);
f(new A()); // 'A'
f(new B()); // 'type 2'
f(new A(0)); // 'val 0'
f(new A(1)); // 'val Number'
// Asynchronous method chain
LazyChain([1, 2])
.lazy(function (v, i, a, e, d) { setTimeout(function () { d.resolve(v * 2) }, 50) }, true)
.map(function (v) { return v * 3 })
.lazy(function (v, i, a, e, d) { setTimeout(function () { d.resolve(v * 10) }, 50) }, true)
.reduce(function (r, v, i, a) { return r + v }, 0)
.forEach(function (v) {
console.log(v); // 180 = (1 * 2 * 3 * 10) + (2 * 2 * 3 * 10)
});
LazyChain($.ajax(''))
.filter(function (v) { return 'object' === typeof v })
.forEach(function (xhr) {
console.log(xhr); // XHR object
});
LazyChain(true);
['./']
.lazy(function (v) { return $.ajax(v) })
.filter(function (v) { return 'object' === typeof v })
.forEach(function (xhr) {
console.log(xhr); // XHR object
});
LazyChain(false);
// Stream generate and control
var a = LazyChain(),
b = LazyChain();
LazyChain(a)
.stream('number', b)
.stream(function (v, i, a, e) {
console.log(v); // 0
});
a.notify(0, '');
b
.stream(function (v, i, a, e) {
console.log(typeof v); // string
});
// Maybe
var Just = Number,
Nothing = Error;
LazyChain<number>([-1, 0, 1, NaN])
.pattern([
Number, n => n > 0,
n => Just(n)
], [
Number,
_ => Nothing()
], [
void 0,
_ => Nothing()
])
.pattern([
Just,
n => Just(n * 100)
])
.pattern([
Just,
n => console.log(Just, n) // 1
], [
Nothing,
e => console.log(Nothing, e)
]);
// Either
type Either = [number, number|typeof Number];
type EitherValue = [number, number];
var LEFT: Either =
[1, Number],
Left =
(data: number) => <EitherValue>[LEFT[0], data],
RIGHT: Either =
[0, Number],
Right =
(data: number) => <EitherValue>[RIGHT[0], data],
Either = {
return: Right,
bind: (m: EitherValue, f: typeof Right|typeof Left) => <EitherValue>f.apply(undefined, [m[1]]),
fail: _ => Left(NaN)
};
var monad =
LazyChain<number>()
.monad<Either>(Either, false)
.monadic([
RIGHT,
data => Right(data + 1)
], [
LEFT,
data => Left(data)
]);
var stream =
LazyChain<number>();
stream
.monad<Either>(Either)
.stream(monad)
.monadic([
RIGHT,
function (data) {
console.log(data); // 1
return Right(data);
}
]);
stream.notify(0);
LazyChain([1, 2, 3], _)
.stream(function (v) {
console.log(v); // 1, 2, 3
})
.difference([1, 3])
.stream(function (v) {
console.log(v); // 2
});
npm i lazychain
Sorry, japanese documents only. I welcome translation.
- IE9+
- Chrome
- Firefox
- Safari
- Android
- iOS
MIT License