-
Notifications
You must be signed in to change notification settings - Fork 25
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
Infrastructure for metaprogramming in pipe/compose (await inside pipe()) #138
Comments
I have a few first impressions. To start, I think that this is really clever and pretty cool. It sounds inevitable that if you use question, does this pipe.await definition drop the right-side functions? // it looks like this:
pipe.await = pipe.do((p, fn) => Promise.await(p));
compose(...leftFns, pipe.await(awaitFn), ...rightFunctions)
// would transform into this:
awaitFn(compose(...leftFns), compose(...rightFns))
// which is the same as:
Promise.await(compose(...leftFns)) When I discovered ferrum, and was asking about generic Point is: I became familiar with using // this
pipe(
leftFns,
asyncFn, // returns Task, not actual promise
task.chain(anotherAsynFn),
task.map(...rightFns)
)()
// or even
pipe(
leftFns,
asyncFn, // returns Task, not actual promise
task.chain(anotherAsynFn)
)()
.then(result => pipe(
result,
...rightFns)
)
)
// over this
pipe(
leftFns,
pipe.await(asyncFn),
pipe.await(anotherAsynFn),
...rightFns)
)() |
No, using Promise.await directly it should transform: compose(...rightFns)(Promise.await(compose(...leftFns)))
Let me just point out that the syntax I was planning to introduce is slightly different from what you used in your comment; the following bit of could wouldn't really happen. // over this
pipe(
leftFns,
pipe.await(asyncFn),
pipe.await(anotherAsynFn),
...rightFns)
)() Instead it would be this: pipe(
leftFns,
asyncFn,
pipe.await,
anotherAsynFn,
pipe.await,
...rightFns)
)() I am not sure how the other code examples could be implemented; there isn't really a task variable anywhere that can be used. However, you could (and already can) easily use then as a free function: const then = curry('then', (p, f) => Promise.resolve(p).then(f));
pipe(
value,
asyncFn,
then(anotherAsyncFn),
then(andAThirdAsyncFn)); |
Provide a generalized pipe/compose metaprogramming infrastructure.
Whenever pipe() (or compose) encounters do, it will evaluate all the functions to the left of the do statement and compose the functions to the right into a single function; passing the value and the functions into the function stored inside to.
We could also use a more general
meta
tuple that allows for generalized rewriting:In this framework do could be implemented as a special case of meta:
Do alone would allow for some interesting transformations on pipe; e.g.
do(ifdef)
would early abort pipe execution anddo(map)
would actually introduce loops as part of the function composition infrastructure.Actually, I believe this would be about as general as the haskell do monad (hence the name) while staying in the fully functional framework.
This is different from the
do
syntax mostly because this uses explicit connectives instead of type dependent connectives as monads to (on the other hand this could be remedied with a type class).Of course, how practical this is would have to be evaluated but the basic use case with await is in my definetly useful.
The text was updated successfully, but these errors were encountered: