Created
December 1, 2024 05:18
-
-
Save duangsuse/3674d747ec5ea8ca510add26295e5a7d to your computer and use it in GitHub Desktop.
脚本语言上想做「非侵入async」,很简单,问题是时延和错误边界的明确性。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!ipy -i | |
def cat(): | |
x=yield '1st' | |
while True: | |
x=yield x | |
z=cat(); next(z) #x=() 待执行 | |
[z.send(n) for n in range(10)] | |
''' | |
有人说 async def 是“红色”,因为不能在蓝的REPL和“带参数脚本”里call它们 | |
没错,async就是允许你setTimeout(retAddr,0s)并return的空函数,你们叫它yield或await。 | |
这样一切回调地狱都能用 await new Promise(ret=> timers.push(1s,ret)) 解决,不是吗? | |
能捕获当前语句/算式号为变量的(ret)叫函续。等返回值卡线程,if分1段执行不完,就必须用 div(10,5,ok), div.bind(10,0)(ok,err) 的回调链表代替调用-返回栈 | |
当然,赋值 global(ThreadLocal) or arg(vueUse) 也行。call-return 还有很多玩法,AOP hook、fndefGC(摇树)、taint污点参数分析和火焰图等等。 fire.py httpie 则是命令行版函数。 | |
脚本语言上想做「非侵入async」,很简单,问题是时延和错误边界的明确性。 | |
come on, 在函参可以随意增长的py里,你没发现 def: yield 和 def: return 这两种调用-返回结构共用“一个颜色”吗? | |
https://gist.github.com/BeautyyuYanli/0a6891d8959bcf06b5cd2e5bd30ef3d1 | |
^^ 认为移植一下 TJ Holowaychuk/co.js 就能bypass这个“红色”问题?其实忽视了设计哲学。 | |
下面我展示下如何从语法上隐藏async的差异,就像那 def: yield 和 def: return | |
''' | |
import asyncio as IO | |
Ctrl=lambda k: wait4(get_ipython().pt_app.key_bindings.add(f'c-{k}')) | |
fname=''' | |
def wait4(needCb): | |
needCb((out:=IO.Future()) .set_result) | |
return out | |
def vscode(): | |
await Ctrl('k') | |
await Ctrl('f') | |
print("close dir!") | |
''' | |
import ast as et | |
def autoAsync(e): | |
e=et.parse(e) | |
iLn=[] | |
class FindAwait(et.NodeTransformer): | |
def visit_FunctionDef(self, f): | |
if any(isinstance(e, et.Await) for e in et.walk(f)): dd(iLn.append)(f.lineno-2) | |
return f | |
FindAwait().visit(e) | |
return sedI(et.unparse(e), iLn,'async ') | |
sedI=lambda s,ai,pre: "\n".join((pre+x if i in ai else x) for i,x in enumerate(s.split('\n'))) | |
dd=lambda f: lambda*a: (v:=f(*a),print(v,*a),v)[-1] | |
exec(dd(autoAsync)(fname)) | |
get_ipython().pt_loop.create_task(vscode()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment