Comparing version 0.2.5 to 0.2.6
160
lib/index.js
@@ -42,9 +42,9 @@ 'use strict'; | ||
endStream.listeners.push(s); | ||
s.toJSON = function() { | ||
return s(); | ||
}; | ||
if (arguments.length > 0) s(initialValue); | ||
return s; | ||
} | ||
// fantasy-land Applicative | ||
flyd.stream['fantasy-land/of'] = flyd.stream.of = flyd.stream; | ||
/** | ||
@@ -189,2 +189,51 @@ * Create a new dependent stream | ||
/** | ||
* Chain a stream | ||
* | ||
* also known as flatMap | ||
* | ||
* Where `fn` returns a stream this function will flatten the resulting streams. | ||
* Every time `fn` is called the context of the returned stream will "switch" to that stream. | ||
* | ||
* __Signature__: `(a -> Stream b) -> Stream a -> Stream b` | ||
* | ||
* @name flyd.chain | ||
* @param {Function} fn - the function that produces the streams to be flattened | ||
* @param {stream} stream - the stream to map | ||
* @return {stream} a new stream with the mapped values | ||
* | ||
* @example | ||
* var filter = flyd.stream('who'); | ||
* var items = flyd.chain(function(filter){ | ||
* return flyd.stream(findUsers(filter)); | ||
* }, filter); | ||
*/ | ||
flyd.chain = curryN(2, chain); | ||
/** | ||
* Apply a stream | ||
* | ||
* Applies the value in `s2` to the function in `s1`. | ||
* | ||
* __Signature__: `Stream (a -> b) -> Stream a -> Stream b` | ||
* | ||
* @name flyd.ap | ||
* @param {stream} s1 - The value to be applied | ||
* @param {stream} s2 - The function expecting the value | ||
* @return {stream} a new stream with the mapped values | ||
* | ||
* @example | ||
* var add = stream(a => b => a + b) | ||
* var n1 = stream(1) | ||
* var n2 = stream(2) | ||
* | ||
* var added = flyd.ap(n2, flyd.ap(n1, add)) // stream(3) | ||
* // can also be written using pipe | ||
* var added_pipe = add | ||
* .pipe(ap(n1)) | ||
* .pipe(ap(n2)); | ||
* added_pipe() // 3 | ||
*/ | ||
flyd.ap = curryN(2, ap); | ||
/** | ||
* Listen to stream events | ||
@@ -338,2 +387,67 @@ * | ||
/** | ||
* Returns the result of applying function `fn` to this stream | ||
* | ||
* __Signature__: Called bound to `Stream a`: `(a -> Stream b) -> Stream b` | ||
* | ||
* @name stream.pipe | ||
* @param {Function} fn - the function to apply | ||
* @return {stream} A new stream | ||
* | ||
* @example | ||
* var numbers = flyd.stream(0); | ||
* var squaredNumbers = numbers.pipe(flyd.map(function(n){ return n*n; })); | ||
*/ | ||
function operator_pipe(f) { return f(this) } | ||
function boundChain(f) { | ||
return chain(f, this); | ||
} | ||
function chain(f, s) { | ||
// Internal state to end flat map stream | ||
var flatEnd = flyd.stream(1); | ||
var internalEnded = flyd.on(function() { | ||
var alive = flatEnd() - 1; | ||
flatEnd(alive); | ||
if (alive <= 0) { | ||
flatEnd.end(true); | ||
} | ||
}); | ||
internalEnded(s.end); | ||
var last = flyd.stream(); | ||
var flatStream = flyd.combine(function(s, own) { | ||
last.end(true) | ||
// Our fn stream makes streams | ||
var newS = f(s()); | ||
flatEnd(flatEnd() + 1); | ||
internalEnded(newS.end); | ||
// Update self on call -- newS is never handed out so deps don't matter | ||
last = flyd.map(own, newS); | ||
}, [s]); | ||
flyd.endsOn(flatEnd.end, flatStream); | ||
return flatStream; | ||
} | ||
flyd.fromPromise = function fromPromise(p) { | ||
var s = flyd.stream(); | ||
p.then(function(val) { | ||
s(val); | ||
s.end(true); | ||
}); | ||
return s; | ||
} | ||
/* istanbul ignore next */ | ||
flyd.flattenPromise = function flattenPromise(s) { | ||
return combine(function(s, self) { | ||
s().then(self); | ||
}, [s]) | ||
} | ||
/** | ||
* Returns a new stream which is the result of applying the | ||
@@ -360,8 +474,18 @@ * functions from `this` stream to the values in `stream` parameter. | ||
*/ | ||
function ap(s2) { | ||
var s1 = this; | ||
function ap(s2, s1) { | ||
return combine(function(s1, s2, self) { self(s1.val(s2.val)); }, [s1, s2]); | ||
} | ||
function boundAp(s2) { | ||
return ap(s2, this); | ||
} | ||
/** | ||
* @private | ||
*/ | ||
function fantasy_land_ap(s1) { | ||
return ap(this, s1); | ||
} | ||
/** | ||
* Get a human readable view of a stream | ||
@@ -417,5 +541,20 @@ * @name stream.toString | ||
s.end = undefined; | ||
s.map = boundMap; | ||
s.ap = ap; | ||
s.of = flyd.stream; | ||
// fantasy-land compatibility | ||
s.ap = boundAp; | ||
s['fantasy-land/map'] = s.map = boundMap; | ||
s['fantasy-land/ap'] = fantasy_land_ap; | ||
s['fantasy-land/of'] = s.of = flyd.stream; | ||
s['fantasy-land/chain'] = s.chain = boundChain; | ||
s.pipe = operator_pipe; | ||
// According to the fantasy-land Applicative specification | ||
// Given a value f, one can access its type representative via the constructor property: | ||
// `f.constructor.of` | ||
s.constructor = flyd.stream; | ||
s.toJSON = function() { | ||
return s.val; | ||
} | ||
s.toString = streamToString; | ||
@@ -545,3 +684,5 @@ return s; | ||
function updateStreamValue(s, n) { | ||
/* istanbul ignore if */ | ||
if (n !== undefined && n !== null && isFunction(n.then)) { | ||
console.warn('flyd: Promise swallowing has been deprecated, please see https://github.com/paldepind/flyd#promises for more info'); | ||
n.then(s); | ||
@@ -630,2 +771,5 @@ return; | ||
* @private | ||
*/ | ||
/** | ||
* @private | ||
* transducer stream transformer | ||
@@ -632,0 +776,0 @@ */ |
var flyd = require('../../lib'); | ||
console.warn('flyd/module/flatmap has been deprecated in favour of flyd.chain'); | ||
/** | ||
@@ -21,28 +23,2 @@ * Given a stream of streams, returns a single stream of merged values | ||
*/ | ||
module.exports = flyd.curryN(2, function(f, s) { | ||
// Internal state to end flat map stream | ||
var flatEnd = flyd.stream(1); | ||
var internalEnded = flyd.on(function() { | ||
var alive = flatEnd() - 1; | ||
flatEnd(alive); | ||
if (alive <= 0) { | ||
flatEnd.end(true); | ||
} | ||
}); | ||
internalEnded(s.end); | ||
var flatStream = flyd.combine(function(s, own) { | ||
// Our fn stream makes streams | ||
var newS = f(s()); | ||
flatEnd(flatEnd() + 1); | ||
internalEnded(newS.end); | ||
// Update self on call -- newS is never handed out so deps don't matter | ||
flyd.on(own, newS); | ||
}, [s]); | ||
flyd.endsOn(flatEnd.end, flatStream); | ||
return flatStream; | ||
}); | ||
module.exports = flyd.chain; |
@@ -24,3 +24,3 @@ # flyd-obj | ||
const flydObj = require('flyd/module/object') | ||
const obj = {x: 1, y: {z: 1}} | ||
const obj = {x: 1, y: {z: 2}} | ||
const objOfStreams = flydObj.streamProps(obj) | ||
@@ -27,0 +27,0 @@ |
{ | ||
"name": "flyd", | ||
"version": "0.2.5", | ||
"version": "0.2.6", | ||
"description": "The less is more, modular, functional reactive programming library", | ||
@@ -11,3 +11,3 @@ "main": "lib/index.js", | ||
"dependencies": { | ||
"ramda": "^0.19.1" | ||
"ramda": "^0.25.0" | ||
}, | ||
@@ -23,2 +23,3 @@ "devDependencies": { | ||
"mocha-lcov-reporter": "0.0.2", | ||
"np": "^2.19.0", | ||
"transducers.js": "0.3.x", | ||
@@ -29,7 +30,9 @@ "uglifyjs": "^2.4.10" | ||
"test-lib": "mocha", | ||
"test": "eslint lib/ test/ module/ && mocha -R dot test/*.js module/**/test/*.js", | ||
"test": "eslint --fix lib/ test/ module/ && mocha -R dot test/*.js module/**/test/*.js", | ||
"docs": "documentation -f md lib/index.js > API.md", | ||
"perf": "./perf/run-benchmarks", | ||
"coverage": "istanbul cover _mocha -- -R spec", | ||
"post-to-coveralls-io": "istanbul cover _mocha --report lcovonly -- -R spec && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage", | ||
"build": "browserify -s flyd lib/index.js > flyd.js && uglifyjs flyd.js -o flyd.min.js" | ||
"build": "browserify -s flyd lib/index.js > flyd.js && uglifyjs flyd.js -o flyd.min.js", | ||
"release": "np" | ||
}, | ||
@@ -36,0 +39,0 @@ "repository": { |
125
README.md
@@ -49,5 +49,2 @@ # Flyd | ||
[Ramda](http://ramdajs.com/) and [transducers.js](https://github.com/jlongster/transducers.js). | ||
* Complies to the [fantasy land](https://github.com/fantasyland/fantasy-land) | ||
applicative specification. | ||
* [Elegant support for promises](#using-promises-for-asynchronous-operations). | ||
* [Atomic updates](#atomic-updates). | ||
@@ -213,17 +210,29 @@ | ||
### Using promises for asynchronous operations | ||
### Promises | ||
Flyd has two helpers for dealing with promises: `flyd.fromPromise` and `flyd.flattenPromise`. | ||
Flyd has inbuilt support for promises. Similarly to how a promise can never be | ||
resolved with a promise, a promise can never flow down a stream. Instead the | ||
fulfilled value of the promise will be sent down the stream. | ||
Let's say you're building a filtered list. It is important to you that the latest filter always corresponds | ||
to the latest promise and its resolution. using `flyd.fromPromise` guarantees the ordering, and can skip intermediate results. | ||
```javascript | ||
var urls = flyd.stream('/something.json'); | ||
var responses = flyd.stream(requestPromise(urls())); | ||
flyd.on(function(responses) { | ||
console.log('Received response!'); | ||
console.log(responses()); | ||
}, responses); | ||
```js | ||
const filter = flyd.stream(''); | ||
const results = filter | ||
.pipe(flyd.chain( | ||
filter => flyd.fromPromise(requestPromise(`https://example.com?q=${filter}`)) | ||
)); | ||
``` | ||
On the other hand let's say you want to sum some numbers from a service you've written. | ||
Every time someone clicks on your site you want to send a request and get back a random number to be tallied. | ||
`flyd.flattenPromise` gives you the guarantee that every promise resolution will be handled, regardless of order. | ||
```js | ||
const clicks = flyd.stream(); | ||
const total = clicks | ||
.map(getNumberAsync) | ||
.pipe(flyd.flattenPromise) | ||
.pipe(flyd.scan((acc, v)=> acc + v, 0)); | ||
``` | ||
### Mapping over a stream | ||
@@ -431,3 +440,57 @@ | ||
``` | ||
### flyd.chain(fn, s) | ||
`fn` must return a stream. | ||
`fn` is run every time a value is pushed into `s`. | ||
Returns a single stream of merged values from the created streams. | ||
Ends when every created stream and the main stream ends | ||
__Signature__ | ||
`(a -> Stream b) -> Stream a -> Stream b` | ||
__Example__ | ||
```javascript | ||
var filter = flyd.stream('filter'); | ||
var search_results = flyd.chain(function(filter){ | ||
return flyd.stream(getResults(filter)); | ||
}, filter); | ||
``` | ||
### flyd.ap(valueStream, functionStream) | ||
Applies the value in `valueStream` to the function in `functionStream` | ||
__Signature__ | ||
`Stream a -> Stream (a -> b) -> Stream b` | ||
__Example__ | ||
```javascript | ||
function add3(x) { return x + 3; } | ||
flyd.ap(flyd.stream(5), flyd.stream(add3)) // stream(8); | ||
``` | ||
while it can not seem useful immediately consider this example | ||
```javascript | ||
var get_results = function (filter, sortProperty, sortDirection) { | ||
return flyd.stream(fetch(`${base_url}/search?q=${filter}&sort=${sortProperty} ${sortDirection}`)) | ||
}; | ||
// this would eventually be linked to an input field | ||
var filter = flyd.stream(''); | ||
var sortProperty = flyd.stream('name'); | ||
var sortDirection = flyd.stream('descending'); | ||
var results = flyd.stream(flyd.curryN(3, get_results)) | ||
.pipe(flyd.ap(filter)) | ||
.pipe(flyd.ap(sortProperty)) | ||
.pipe(flyd.ap(sortDirection)) | ||
.pipe(flyd.map(function(d){ return d; })); | ||
``` | ||
In the above example you have a stream of results that triggers a call for get_results | ||
every time `filter`, `sortProperty`, or `sortDirection` is changed. | ||
### flyd.on(fn, s) | ||
@@ -561,4 +624,33 @@ | ||
### stream.map(f) | ||
### stream.pipe(fn) | ||
Returns the result of applying function `fn` to the stream. | ||
__Signature__ | ||
Called bound to `Stream a`: `(Stream a -> Stream b) -> Stream b` | ||
__Example__ | ||
```javascript | ||
// map a stream | ||
var numbers = flyd.stream(0); | ||
var squaredNumbers = numbers | ||
.pipe(flyd.map(function(n) { return n*n; })); | ||
// Chain a stream | ||
var filter = flyd.stream('filter'); | ||
var search_results = filter | ||
.pipe(flyd.chain(function(filter){ | ||
return flyd.stream(getResults(filter)); | ||
})); | ||
// use with a flyd module | ||
var filter = require('flyd/module/filter'); | ||
var numbers = flyd.stream(0); | ||
var isEven = function(x){ return x % 2 === 0; }; | ||
var evenNumbers = numbers | ||
.pipe(filter(isEven)); | ||
``` | ||
### stream.map(f) __Deprecated__ | ||
Returns a new stream identical to the original except every | ||
@@ -581,3 +673,3 @@ value will be passed through `f`. | ||
### stream1.ap(stream2) | ||
### stream1.ap(stream2) __Deprecated__ | ||
@@ -632,3 +724,2 @@ `stream1` must be a stream of functions. | ||
| [flyd/module/**lift**](module/lift) | Maps a function taking _n_ parameters over _n_ streams. | | ||
| [flyd/module/**flatmap**](module/flatmap) | Maps a function over a stream of streams and flattens the result to a single stream. | | ||
| [flyd/module/**switchlatest**](module/switchlatest) | Flattens a stream of streams. The result stream reflects changes from the last stream only. | | ||
@@ -635,0 +726,0 @@ | [flyd/module/**keepwhen**](module/keepwhen) | Keep values from one stream only when another stream is true. | |
@@ -9,2 +9,5 @@ var assert = require('assert'); | ||
var combine = flyd.combine; | ||
var map = flyd.map; | ||
var ap = flyd.ap; | ||
var chain = flyd.chain; | ||
@@ -36,3 +39,3 @@ // Some combinators | ||
str: stream('string'), | ||
obj: stream({is_object: true}) | ||
obj: stream({ is_object: true }) | ||
}; | ||
@@ -252,6 +255,6 @@ var expected_outcome = { | ||
var result; | ||
stream(1).map(function() { | ||
stream(1).pipe(map(function() { | ||
var n = flyd.stream(1); | ||
n.map(function(v) { result = v + 100; }); | ||
}); | ||
n.pipe(map(function(v) { result = v + 100; })); | ||
})); | ||
assert.equal(result, 101); | ||
@@ -261,7 +264,7 @@ }); | ||
var result; | ||
stream(1).map(function() { | ||
stream(1).pipe(map(function() { | ||
var n = stream(); | ||
n.map(function(v) { result = v + 100; }); | ||
n.pipe(map(function(v) { result = v + 100; })); | ||
n(1); | ||
}); | ||
})); | ||
assert.equal(result, 101); | ||
@@ -271,9 +274,9 @@ }); | ||
var result = undefined; | ||
stream(1).map(function() { | ||
stream(1).pipe(map(function() { | ||
var n = stream(); | ||
n.map(function(v) { result = v + 100; }); | ||
n.pipe(map(function(v) { result = v + 100; })); | ||
n.end(true); | ||
n(1); | ||
n(2); | ||
}); | ||
})); | ||
assert.equal(result, undefined); | ||
@@ -374,5 +377,5 @@ }); | ||
describe('promise integration', function() { | ||
describe('promise swallowing', function() { | ||
it('pushes result of promise down the stream', function(done) { | ||
var s = stream(); | ||
var s = flyd.fromPromise(Promise.resolve(12)); | ||
combine(function(s) { | ||
@@ -382,11 +385,5 @@ assert.equal(s(), 12); | ||
}, [s]); | ||
s(Promise.resolve(12)); | ||
}); | ||
it('recursively unpacks promise', function(done) { | ||
var s = stream(); | ||
combine(function(s) { | ||
assert.equal(s(), 12); | ||
done(); | ||
}, [s]); | ||
s(new Promise(function(res) { | ||
var s = flyd.fromPromise(new Promise(function(res) { | ||
setTimeout(function() { | ||
@@ -398,2 +395,6 @@ res(new Promise(function(res) { | ||
})); | ||
combine(function(s) { | ||
assert.equal(s(), 12); | ||
done(); | ||
}, [s]); | ||
}); | ||
@@ -416,3 +417,3 @@ }); | ||
var x = stream(3); | ||
var doubleX = x.map(function(x) { return 2 * x; }); | ||
var doubleX = x.pipe(map(function(x) { return 2 * x; })); | ||
assert.equal(doubleX(), 6); | ||
@@ -449,3 +450,3 @@ x(1); | ||
var x = stream(3); | ||
var x2 = x.map(function(a) { return a; }); | ||
var x2 = x.pipe(map(function(a) { return a; })); | ||
assert.equal(x2(), x()); | ||
@@ -459,4 +460,4 @@ x('foo'); | ||
var x = stream(3); | ||
var s1 = x.map(g).map(f); | ||
var s2 = x.map(function(x) { return f(g(x)); }); | ||
var s1 = x.pipe(map(g)).pipe(map(f)); | ||
var s2 = x.pipe(map(function(x) { return f(g(x)); })); | ||
assert.equal(s1(), s2()); | ||
@@ -468,2 +469,84 @@ x(12); | ||
describe('chain', function() { | ||
it('applies function to values in stream', function() { | ||
var result = []; | ||
function f(v) { | ||
result.push(v); | ||
return stream(); | ||
} | ||
var s = stream(); | ||
flyd.chain(f, s); | ||
s(1)(2)(3)(4)(5); | ||
assert.deepEqual(result, [1, 2, 3, 4, 5]); | ||
}); | ||
it('returns stream with result from all streams created by function', function() { | ||
var result = []; | ||
function f(v) { | ||
var s = stream(); | ||
setImmediate(function() { | ||
s(v + 1)(v + 2)(v + 3); | ||
}); | ||
return s; | ||
} | ||
var s = stream(); | ||
flyd.map(function(v) { | ||
result.push(v); | ||
}, flyd.chain(f, s)); | ||
s(1)(3)(5); | ||
setImmediate(function() { | ||
assert.deepEqual(result, [2, 3, 4, | ||
4, 5, 6, | ||
6, 7, 8]); | ||
}); | ||
}); | ||
it('passed bug outlined in https://github.com/paldepind/flyd/issues/31', function(done) { | ||
function delay(val, ms) { | ||
var outStream = flyd.stream(); | ||
setTimeout(function() { | ||
outStream(val); | ||
outStream.end(true); | ||
}, ms); | ||
return outStream; | ||
} | ||
var main = delay(1, 500); | ||
var merged = flyd.chain(function(v) { | ||
return delay(v, 1000) | ||
}, main); | ||
flyd.on(function() { | ||
assert(main() === 1); | ||
assert(merged() === 1); | ||
done(); | ||
}, merged.end); | ||
}); | ||
it('preserves ordering', function() { | ||
function delay(val, ms) { | ||
var outStream = flyd.stream(); | ||
setTimeout(function() { | ||
outStream(val); | ||
outStream.end(true); | ||
}, ms); | ||
return outStream; | ||
} | ||
var s = stream(); | ||
var s2 = s | ||
.pipe(chain(function(val) { | ||
return delay(val, 100); | ||
})); | ||
s(1)(2)(3)(4); | ||
flyd.on(function(val) { | ||
assert.equal(val, 4); | ||
}, s2) | ||
}); | ||
}); | ||
describe('scan', function() { | ||
@@ -573,3 +656,3 @@ it('has initial acc as value when stream is undefined', function() { | ||
var v = stream(3); | ||
var s = a.ap(v); | ||
var s = a.pipe(ap(v)); | ||
assert.equal(s(), 6); | ||
@@ -585,10 +668,13 @@ a(function(x) { return x / 3; }); | ||
var v = stream(8); | ||
var s1 = a.map(function(f) { | ||
return function(g) { | ||
return function(x) { | ||
return f(g(x)); | ||
var s1 = a | ||
.pipe(map(function(f) { | ||
return function(g) { | ||
return function(x) { | ||
return f(g(x)); | ||
}; | ||
}; | ||
}; | ||
}).ap(u).ap(v); | ||
var s2 = a.ap(u.ap(v)); | ||
})) | ||
.pipe(ap(u)) | ||
.pipe(ap(v)); | ||
var s2 = a.pipe(ap(u.pipe(ap(v)))); | ||
assert.equal(s1(), 26); | ||
@@ -614,3 +700,3 @@ assert.equal(s2(), 26); | ||
var s3 = stream(0); | ||
var sum = flyd.map(sumThree, s1).ap(s2).ap(s3); | ||
var sum = flyd.map(sumThree, s1).pipe(ap(s2)).pipe(ap(s3)); | ||
flyd.map(function(v) { result.push(v); }, sum); | ||
@@ -626,3 +712,3 @@ s1(3); s2(2); s3(5); | ||
var addToNumbers1 = flyd.map(add, numbers1); | ||
var added = addToNumbers1.ap(numbers2); | ||
var added = addToNumbers1.pipe(ap(numbers2)); | ||
flyd.map(function(n) { result.push(n); }, added); | ||
@@ -635,2 +721,10 @@ numbers1(3); numbers2(2); numbers1(4); | ||
describe('of', function() { | ||
it('can be accessed through the constructor property', function() { | ||
var s1 = stream(2); | ||
var s2 = s1.constructor.of(3); | ||
var s3 = s2.constructor['fantasy-land/of'](3); | ||
assert.equal(flyd.isStream(s2), true); | ||
assert.equal(s2(), 3); | ||
assert.equal(s3(), 3); | ||
}); | ||
it('returns a stream with the passed value', function() { | ||
@@ -645,3 +739,3 @@ var s1 = stream(2); | ||
var v = stream(12); | ||
assert.equal(a.of(id).ap(v)(), v()); | ||
assert.equal(a.of(id).pipe(ap(v))(), v()); | ||
}); | ||
@@ -652,3 +746,3 @@ it('is homomorphic', function() { | ||
var x = 12; | ||
assert.equal(a.of(f).ap(a.of(x))(), a.of(f(x))()); | ||
assert.equal(a.of(f).pipe(ap(a.of(x)))(), a.of(f(x))()); | ||
}); | ||
@@ -659,4 +753,4 @@ it('is interchangeable', function() { | ||
var u = stream()(function(x) { return 3 * x; }); | ||
assert.equal(u.ap(a.of(y))(), | ||
a.of(function(f) { return f(y); }).ap(u)()); | ||
assert.equal(u.pipe(ap(a.of(y)))(), | ||
a.of(function(f) { return f(y); }).pipe(ap(u))()); | ||
}); | ||
@@ -685,3 +779,3 @@ it('can create dependent stream inside stream', function() { | ||
// create a stream, the first dependant on `str` should still be updated | ||
flyd.combine(function() {}, []); | ||
flyd.combine(function() { }, []); | ||
}, str); | ||
@@ -849,3 +943,3 @@ str(1); | ||
flyd.combine(function(a,b,c,d,e,f,g,self,changed) { | ||
flyd.combine(function(a, b, c, d, e, f, g, self, changed) { | ||
var vals = changed.map(function(s) { return s(); }); | ||
@@ -861,2 +955,41 @@ result.push(vals); | ||
}); | ||
describe('fantasy-land', function() { | ||
it('map', function() { | ||
var s = stream(1); | ||
var mapped = R.map(R.add(3), s); | ||
assert.equal(mapped(), 4); | ||
assert.equal(s(), 1); | ||
}); | ||
it('chain', function() { | ||
var s = stream(1); | ||
var chained = R.chain(R.compose(stream, R.add(3)), s); | ||
assert.equal(chained(), 4); | ||
assert.equal(s(), 1); | ||
}); | ||
it('ap', function() { | ||
var s = stream(R.add(3)); | ||
var val = stream(3); | ||
var applied = R.ap(s, val); | ||
assert.equal(applied(), 6); | ||
}); | ||
it('old ap', function() { | ||
var s = stream(R.add(3)) | ||
.ap(stream(3)); | ||
assert.equal(s(), 6); | ||
}); | ||
it('of', function() { | ||
var s = flyd.stream(3); | ||
var s2 = s['fantasy-land/of'](5); | ||
assert(flyd.isStream(s)); | ||
assert.equal(s(), 3); | ||
assert(flyd.isStream(s2)); | ||
assert.equal(s2(), 5); | ||
}) | ||
}); | ||
}); |
245501
5631
815
11
+ Addedramda@0.25.0(transitive)
- Removedramda@0.19.1(transitive)
Updatedramda@^0.25.0