Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to classes #34

Merged
merged 34 commits into from
Oct 18, 2016
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5877bd3
WIP: Convert several methods from higher-order style to class-style
Avaq Oct 9, 2016
6eb1fe5
Fix test-opt script
Avaq Oct 14, 2016
5727d43
Refactor Future.cache
Avaq Oct 15, 2016
36bd594
Remove Future#recur in favor of Future.chainRec
Avaq Oct 15, 2016
ea78cd8
Fix bench/curry
Avaq Oct 15, 2016
56144ca
Refactor chainRej
Avaq Oct 15, 2016
3e893c8
Correct a typo
Avaq Oct 15, 2016
0a43aa3
Refactor mapRej
Avaq Oct 15, 2016
f144ccc
Refactor Future.bimap
Avaq Oct 15, 2016
471ece7
Fix inspect methods
Avaq Oct 15, 2016
b7294fa
Refactor Future.swap
Avaq Oct 15, 2016
f4bfa3d
Add race benchmark
Avaq Oct 15, 2016
aa6a3a7
Refactor Future.race
Avaq Oct 15, 2016
e34f1a6
Add Future.or benchmark
Avaq Oct 15, 2016
7041f53
Refactor Future.or
Avaq Oct 15, 2016
becca2d
Refactor Future.fold
Avaq Oct 15, 2016
1e5482e
Use normal toString semantics for CachedFuture
Avaq Oct 15, 2016
6815f14
Refactor Future.hook
Avaq Oct 15, 2016
f86f468
Refactor Future.finally
Avaq Oct 15, 2016
05f54e1
Move stuff around
Avaq Oct 16, 2016
b17a52a
Refactor static utilities to introspective classes
Avaq Oct 16, 2016
2cd49ef
Add Future.parallel benchmark
Avaq Oct 16, 2016
14157c6
Performance optimize Future.parallel
Avaq Oct 16, 2016
72bc0dc
Fix a bug in CachedFuture
Avaq Oct 16, 2016
b223ff8
Restore code coverage
Avaq Oct 17, 2016
2ca9baf
Improve curry benchmark, check perf diff between 3 ifs and switch
Avaq Oct 18, 2016
51f8930
Improve the Future#hook readme example
Avaq Oct 18, 2016
ee9e247
Remove excess brackets from encase unit tests
Avaq Oct 18, 2016
904c1be
Remove excess brackets from isFuture check
Avaq Oct 18, 2016
405bf3c
Improve code for Future.encaseN functions
Avaq Oct 18, 2016
27afcc7
Use named states in ChainRec
Avaq Oct 18, 2016
a4edcbf
Use named states in CachedFuture
Avaq Oct 18, 2016
fabb2fc
Optimization: `ok += 1` -> `ok = ok + 1`
Avaq Oct 18, 2016
ebc46b0
Replace "if a then a else b" ternary operators with "a or b"
Avaq Oct 18, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@
"no-trailing-spaces": 2,
"no-unneeded-ternary": 2,
"object-curly-spacing": [2, "never"],
"operator-linebreak": [2, "before"],
"padded-blocks": 0,
"semi-spacing": [2, {"before": false, "after": true}],
"space-before-blocks": [2, "never"],
Expand Down
44 changes: 24 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ getPackageName('package.json')
* [map](#map)
* [bimap](#bimap)
* [chain](#chain)
* [recur](#recur)
* [ap](#ap)
* [swap](#swap)
1. [Error handling](#error-handling)
Expand Down Expand Up @@ -331,19 +330,10 @@ Future.of(1)
//> 2
```

#### recur
##### `#recur :: Future a b ~> (b -> Future a c) -> Future a c`
##### `.recur :: (b -> Future a c) -> Future a b -> Future a c`

An alternative version of `chain` which does not build up the cancel function.
This is useful in the case of a never-resolving recursive computation, in
order to prevent stack-overflow or out-of-memory errors:

```js
const recursive = () => Future.after(200, 'world').recur(recursive);
const cancel = recursive();
process.on('SIGINT', cancel);
```
Note that, due to its lazy nature, the stack and/or heap will slowly fill up as
you chain more over the same structure. It's therefore recommended that you use
[`chainRec`](#chainrec) in cases where you wish to `chain` recursively or
traverse a large list (10000+ items).

#### ap
##### `#ap :: Future a b ~> Future a (b -> c) -> Future a c`
Expand Down Expand Up @@ -465,13 +455,27 @@ withConnection(
.fork(console.error, console.log)
```

Be careful when cancelling a hooked Future. If the resource was acquired but not
yet consumed, it will no longer be disposed. One way to work around this is to
have the `consume` computation return a cancel function which forcefully
disposes of the resource.
In the case that a hooked Future is *cancelled* after the resource was acquired,
`dispose` will be executed and immediately cancelled. This means that rejections
which may happen during this disposal are **silently ignored**. To ensure that
resources are disposed during cancellation, you might synchronously dispose
resources in the `cancel` function of the disposal Future:

```js
const closeConnection = conn => Future((rej, res) => {

//We try to dispose gracefully.
conn.flushGracefully(err => {
if(err) return rej(err);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you writing return rej(err); to save yourself from typing { rej(err); return; }? If so, I urge you to reconsider as it makes the lambda's return value appear to be significant. I'd find this clearer:

if (err == null) {
  conn.close();
  res();
} else {
  rej(err);
}

conn.close();
res();
});

//On cancel, we force dispose.
return () => conn.close();

Take care when using this in combination with [`cache`](#cache). Hooking relies
on the first operation providing a fresh resource every time it's forked.
});
```

#### finally
##### `#finally :: Future a b ~> Future a c -> Future a b`
Expand Down
2 changes: 1 addition & 1 deletion bench/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ suite.add('Fluture', () => {
});

suite.add('Ramda Fantasy', () => {
const future = RamdaFuture.cache(Fluture.of(1));
const future = RamdaFuture.cache(RamdaFuture.of(1));
addTenMaps(future);
future.fork(noop, noop);
});
Expand Down
28 changes: 28 additions & 0 deletions bench/or.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const benchmark = require('benchmark');
const suite = new benchmark.Suite();
const Future = require('..');

const noop = () => {};
const a = Future.of('a');
const b = Future.of('b');
const _a = Future.reject('!a');
const _b = Future.reject('!b');

suite.add('res res', () => {
a.or(b).fork(noop, noop);
});

suite.add('rej rej', () => {
_a.or(_b).fork(noop, noop);
});

suite.add('rej res', () => {
_a.or(b).fork(noop, noop);
});

suite.add('res rej', () => {
a.or(_b).fork(noop, noop);
});

suite.on('complete', require('./_print'))
suite.run()
32 changes: 32 additions & 0 deletions bench/parallel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const benchmark = require('benchmark');
const suite = new benchmark.Suite();
const Future = require('..');

const noop = () => {};
const makeArr = length => Array.from({length}, (_, i) => Future.of(i));
const empty = makeArr(0);
const small = makeArr(2);
const big = makeArr(100);

suite.add('Empty', () => {
Future.parallel(1, empty).fork(noop, noop);
});

suite.add('Small concurrent', () => {
Future.parallel(2, small).fork(noop, noop);
});

suite.add('Small sequential', () => {
Future.parallel(1, small).fork(noop, noop);
});

suite.add('Big concurrent', () => {
Future.parallel(Infinity, big).fork(noop, noop);
});

suite.add('Big sequential', () => {
Future.parallel(5, big).fork(noop, noop);
});

suite.on('complete', require('./_print'))
suite.run()
26 changes: 26 additions & 0 deletions bench/race.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const benchmark = require('benchmark');
const suite = new benchmark.Suite();
const Future = require('..');

const noop = () => {};
const a = Future.of('a');
const b = Future.after(5, 'b');

suite.add('Left winner', () => {
a.race(b).fork(noop, noop);
});

suite.add('Right winner', () => {
b.race(a).fork(noop, noop);
});

suite.add('Both fast', () => {
a.race(a).fork(noop, noop);
});

suite.add('Both slow', () => {
b.race(b).fork(noop, noop);
});

suite.on('complete', require('./_print'))
suite.run()
Loading