> On Feb 10, 2020, at 02:34, Bar Harel <bha...@barharel.com> wrote:
> 
> While I'm not this idea can totally work, I do think we need a method of 
> closing the gap between asyc coroutines and normal functions.
> 
> As of today, async applications need to create an entirely different 
> codebase, sometimes just by copy and paste, while changing function 
> definitions to async and function calls to await. 
> 
> This creates a lot of work, from porting code to maintaining both variants, 
> to just having code duplication all around.

It’s a well-known problem that async is “contagious”: once you turn one 
function into a coroutine, you have to turn the whole call tree async up to 
some point where you can either block or daemonize a coroutine. Together with 
the fact that async operations have not just different syntax but different 
names and APIs than their sync equivalents, this makes it hard to port code 
between the two paradigms.

But C# and every other language that’s borrowed the idea has the same problem, 
and as far as I know, nobody’s thought of a good answer yet. Just saying “this 
is bad, so we should do something” doesn’t get us anywhere unless that 
something is doable and solves the problem and we know what it is. And I don’t 
know if that’s the case here. The OP proposed something that can only work by 
impossible magic, and you suggested it would be nice if we had something 
actually implementable that was just as easy to use, and it definitely would be 
nice, but unless someone has an idea for that something… (That definitely 
doesn’t mean it isn’t worth pursuing. Just because nobody else has thought of 
it yet doesn’t mean it’s impossible, after all.)

I think breaking down decorators into smaller building blocks that can be 
composed might be promising. If you have a 30 different decorators that all 
want to do something (that doesn’t block) before calling the wrapper function 
or coro, you can write a single `@before` that does have to duplicate its code 
and then 30 decorators that use `before` and don’t need any duplication. I’m 
not sure how far you can get with that. Certainly not all the way to the full 
generality of arbitrary-code decorators (although I don’t think even the OP’s 
magic would get use there—you still can’t put any code into the decorator that 
might be blocking except for the wrapped function, especially since usually the 
difference isn’t just a matter of await or not, but of calling a different 
method on a different object…). But maybe far enough to be useful? I don’t know.

Another possible avenue is to drop back a level and write wrappers that work on 
futures. Async futures and concurrent futures duck type as 
lowest-common-denominator futures, and maybe some of the helpers you want can 
be built that way without duplicating their code?

Meanwhile, for porting large existing threaded or synchronous codebases, you 
may be better off using the gevent model, where awaiting is internal and 
invisible. You can find out pretty quickly whether all of your libraries are 
compatible or not. If they are, you won’t get all of the advantages (e.g., with 
await it’s often obvious when you can remove a mutex or other sync object; with 
gevent, because it looks nearly identical to preemptive threading, if that 
mutex was necessary in the preemptive version, it still looks necessary in the 
gevent version even though it isn’t, unless you think it through carefully), 
but only having to rewrite 2% of your code instead of 60% may be worth it 
anyway. Just because asyncio is usually the best model for new code doesn’t 
mean it’s the always best model for porting all code. 

_______________________________________________
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/P2VO5LUXM5S2IH3YL7QKGZWVSKVLCTAL/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to