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
Add Future[A] that helps with async code #274
Comments
A perhaps more interesting example: await (
Promise(delay([1,2,3]))
.map(partial(map, double)) # double each entry
.map(partial(map, double_async)) # double each entry with a coroutine
.bind(star_gather) # gather the result with a coroutine
)
# ==> [4, 8, 12] where async def star_gather(list_of_coros):
return await asyncio.gather(*list_of_coros) |
Hi, @SaschaSchlemmer! Thanks a lot! This is indeed on our list: #235 I will close that issue and keep this one to discuss this topic. The problem with P.S. Considering |
actually the above implementation is not tied to asyncio. It just uses python 3.6 |
We also would probably need things like:
I consider all tasks to be |
I'd not consider everything IO, and I'd also avoid the name |
Fair enough about What's your opinion about not being |
Yes, there are definitely use cases where coroutines are not just used for IO; in particular there is |
I've got a couple of examples that help to better understand what this whole synchronous vs asynchronous/concurrent vs parallel business is all about (and how this would look like using def double(x: int) -> int:
time.sleep(1)
return 2*x
async def double_async(x: int) -> int:
await asyncio.sleep(1)
return 2*x Test cases:
|
Notice that I added another usage example at the bottom of my original post :) |
Also it appears typing with mypy works out of the box (and without requiring a plugin): from __future__ import annotations
from typing import Generic, TypeVar, Callable, Awaitable
A = TypeVar('A')
B = TypeVar('B')
class Continuation(Generic[A]):
def __init__(self, coro: Awaitable[A]):
self._coro = coro
@classmethod
def unit(cls, value: A) -> Continuation[A]:
async def coro() -> A:
return value
return cls(coro())
def map(self, f: Callable[[A], B]) -> Continuation[B]:
async def coro() -> B:
x = await self._coro
return f(x)
return Continuation(coro())
def bind(self, f: Callable[[A], Awaitable[B]]) -> Continuation[B]:
async def coro() -> B:
x = await self._coro
return await f(x)
return Continuation(coro())
def __await__(self):
return self._coro.__await__() After some googl'ing around I came to the conclusion that |
Yes, I like And we can start a detailed discussion from there. |
Over the weekend I will probably have some spare time to work on this :) I also played around with lists of continuations (I implemented another monad |
Sry for not responding for a while, been very busy; seems to me the code you linked does basically the same and adds some features my proposal didn't have as well. |
I have created an issue in the |
That sounds like a good idea |
I also like the idea that And that's how Python really works. You cannot just can a coroutine. You have to use an executor like I also like this idea, because it will simplify the implementation. No need for separate |
Ok, maybe |
Really interesting project https://github.com/h2non/paco |
We would also need to rework:
|
After playing around
|
Related #355 |
These methods are left to finish
|
Unit methods:
|
Pointfree:
|
I am lately writing a lot of asynchronous code (using asyncio mostly) and while
async
/await
is fairly straight forward and nice to work with, it hinders writing modular code with small functions and reuse of said functions. This is imho due to two issues in particular:def foo(...
and coroutinesasync def bar(...
have different calling semantics. For a regular function you just dofoo(...)
to get your result back while for coroutines you need to await the result, i.e. useawait bar(...)
await
all over your code)Let's define a couple simple functions (both regular and coroutines) to illustrate these issues:
Cases:
Composing regular functions just for reference - easy:
Composing regular and coroutine functions V1 - not so bad,:
Composing regular and coroutine functions V2 - awkward with the await thrown into the middle:
Composing two coroutine functions -
await
s galore :To ease this pain I propose a (monad-like) container that implements
map
andbind
so that functions can be chained nicelyUsage
async def
) to create an instance ofPromise
.Promise
Promise
Extended example
Since the examples above don't look too intimidating, behold:
vs.:
Feedback greatly appreciated!
The text was updated successfully, but these errors were encountered: