Add support for async/await in the lambda expression.

Feature or enhancement

Need support for async/await in the lambda expression.

Pitch

I found meaningful use cases for async lambda in reactive programming. Here is the example code that should be:

async def read_one_by_id(request: ReadOneByIdRequest) -> Content[Account]:
    return rx.just(request).pipe(
        ops.map(async lambda request: await account_repository.read_one_by_id(request.id)),
        ops.map(lambda entity: Content(data=entity, message="Account read one by id succeed.")),
        ops.catch(lambda exception, source: rx.just(
            Content(entity=None, message=f"Account read one by id failed: {exception}")))
    ).run()

Previous discussion

1 Like

I’m not against the idea, but I also don’t see any justification for it in your example. As far as I can tell, your entire example is synchronous, except for a sprinkling of async and await keywords in a lambda definition. It’s not clear to me how that asynchronous lambda is meant to be actually run there, though.

My personal preference for the color of the bikeshed would be async lambda <args>: <awaitable expr>. Just like how lambda <args>: <expr> logically expands to def <lambda>(<args>): return <expr> with an implicit return, async lambda would expand to async def <lambda>(<args>): return await <awaitable expr> with implicit return await. Edit: On second thought, the await probably should not be implicit; that would prevent things like async lambda i: await func1(i) or await func2(i). I definitely think it ought to be async lambda rather than lambda async, though.

In a lot of cases, you can (or at least, should be able to if your runner is not too restrictive :slight_smile: ) just use a regular lambda that returns an awaitable to get most of the benefit that an async lambda would provide. A restrictive runner that checks inspect.iscoroutinefunction(func) is about the only case where I see real utility in an async lambda, and I would argue that’s more of a problem with the runner than a syntax deficiency.

2 Likes

Concur with Zachary.

I’ve thought about this idea before. And I came to the conclusion that in the simplest cases you can use a simple synchronous lambda returning an awaitable, and in more complex cases it is better to use a named internal function. Each async and await increase the length of the line, therefore the use of async lambda will not help with readability too much.

4 Likes

I like this idea. I personally think that instead of async lambda: await something
it should be alambda: await something
however, you can also make a wrapper function to do the same thing:

def alambda(x, *args, **kwds):
    async def wrapped():
        return x(*args, **kwds)