-
Notifications
You must be signed in to change notification settings - Fork 35
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
Future #432
base: master
Are you sure you want to change the base?
Future #432
Conversation
ping @nechaido |
} | ||
}) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this perhaps be rewritten without double Future?
map(fn) {
return new Future((resolve, reject) => {
this.run(value => {
try {
resolve(fn(value));
} catch (error) {
reject(error);
}
});
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing the attention here!
I was able to spot the inconsistency of error handling.
The ideologically correct way to implement map
function for any monad is the application of chain
to the composition of of
and fn
. Rambda did it.
To do it here one simply needs to move error checking from here to run
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation of map
through already existed chain
and of
is less efficient because of the creation of two Futures. That said such implementation reuses code and is the same for any monad. Though the duplicated code here is tiny meaning it may be allowed here for clarity.
So there is a tradeoff between performance and ideological purity here :-)
|
||
promise() { | ||
return new Promise((resolve, reject) => { | ||
this.run(value => resolve(value), error => reject(error)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.run(value => resolve(value), error => reject(error)); | |
this.run(value => resolve(value), reject); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the lambda is used for dropping other arguments
|
||
chain(fn) { | ||
return new Future((resolve, reject) => | ||
this.run(value => fn(value).run(resolve, reject), error => reject(error)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.run(value => fn(value).run(resolve, reject), error => reject(error)) | |
this.run(value => fn(value).run(resolve, reject), reject) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
const { Future, futurify } = require('..'); | ||
const metatests = require('metatests'); | ||
|
||
metatests.test('Future map/run', async test => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
metatests.test('Future map/run', async test => { | |
metatests.test('Future map/run', test => { |
?
(and in other tests)
|
||
metatests.test('Future stateless', async test => { | ||
const f1 = Future.of(3); | ||
const f2 = f1.map(x => ++x); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const f2 = f1.map(x => ++x); | |
const f2 = f1.map(x => x + 1); |
.map(() => { | ||
throw new Error('msg'); | ||
}) | ||
.run(test.mustNotCall, error => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.run(test.mustNotCall, error => { | |
.run(test.mustNotCall(), error => { |
} | ||
}) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for bringing the attention here!
I was able to spot the inconsistency of error handling.
The ideologically correct way to implement map
function for any monad is the application of chain
to the composition of of
and fn
. Rambda did it.
To do it here one simply needs to move error checking from here to run
method.
} | ||
|
||
run(successed, failed) { | ||
this.executor(successed, failed); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's important to catch errors the executor
may throw. It will also allow omitting error handling in the map
method
} | ||
}) | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Implementation of map
through already existed chain
and of
is less efficient because of the creation of two Futures. That said such implementation reuses code and is the same for any monad. Though the duplicated code here is tiny meaning it may be allowed here for clarity.
So there is a tradeoff between performance and ideological purity here :-)
Closes: #431